环境:linux7 内核3.10 2台 192.168.13.111 192.168.13.222
之前在windows整合过单机版的elasticsearch,对于SpringBoot项目来说变动几乎没有,唯一的就是多节点配置下。
2台机器已安装docker
pull elasticsearch镜像
每台机器创建三个文件夹分别放数据、日志和配置文件
两台机器都一样的文件夹
需要给文件夹权限chmod 777 elasticsearch6.7.1/ 必须,切记!6.x版本必须给权限,必须,必须
在111的机器config文件夹下面创建elasticsearch.yml配置文件
#集群名称,所有节点的集群名称必须保持一致
cluster.name: elasticsearch
#节点名称
node.name: es111
#允许哪些IP可以访问,全部通过
network.bind_host: 0.0.0.0
#发布到外部服务的IP
network.publish_host: 192.168.13.111
#访问的端口,默认9200
http.port: 9200
#外部服务交互端口,比如java等
transport.tcp.port: 9300
#head插件跨域访问设置为true
http.cors.enabled: true
http.cors.allow-origin: "*"
#可以有资格竞选master
node.master: true
#存储数据
node.data: true
#集群节点,发现其他服务器中的es服务,可以不指定端口[默认9300],如果是发现同一个服务器中的es服务,#就需要指定端口了
discovery.zen.ping.unicast.hosts: ["192.168.13.111","192.168.13.222"]
#避免脑裂,一般集群服务器都是奇数,而且设置都是过半+1,这里只有2台,就设置1了
discovery.zen.minimum_master_nodes: 1
在222机器的config文件夹下面创建elasticsearch.yml配置文件:
#集群名称,所有节点的集群名称必须保持一致
cluster.name: elasticsearch
#节点名称
node.name: es222
#允许哪些IP可以访问,全部通过
network.bind_host: 0.0.0.0
#发布到外部服务的IP
network.publish_host: 192.168.13.222
#访问的端口,默认9200
http.port: 9200
#外部服务交互端口,比如java等
transport.tcp.port: 9300
#head插件跨域访问设置为true
http.cors.enabled: true
http.cors.allow-origin: "*"
#可以有资格去竞选master
node.master: true
#存储数据
node.data: true
#集群节点,发现其他服务器中的es服务,可以不指定端口[默认9300],如果是发现同一个服务器中的es服务,#就需要指定端口了
discovery.zen.ping.unicast.hosts: ["192.168.13.111","192.168.13.222"]
#避免脑裂,一般集群服务器都是奇数,而且设置都是过半+1,这里只有2台,就设置1了
discovery.zen.minimum_master_nodes: 1
在111机器执行docker命令:看看elasticsearch是否启动
docker run -d --name es111 -p 9200:9200 -p 9300:9300 -v /elasticsearch6.7.1/config:/usr/share/elasticsearch/config -v /elasticsearch6.7.1/data:/usr/share/elasticsearch/data elasticsearch:6.7.1
浏览器访问:192.168.13.111:9200看效果,访问不到。ES启动后马上就停了
于是查看日志 docker logs -f es111或者容器ID 内存不足
更换启动方式,给予内存分配
docker run -d --name es111 -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -p 9200:9200 -p 9300:9300 -v /elasticsearch6.7.1/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /elasticsearch6.7.1/data:/usr/share/elasticsearch/data elasticsearch:6.7.1
Xms和Xmx要一样,否则会提示内存错误: bootstrap checks failed
[1]: initial heap size [268435456] not equal to maximum heap size [536870912]; this can cause resize pauses and prevents mlockall from locking the entire heap
在222机器执行同样docker命令(这里取名es222):
docker run -d --name es111 -e ES_JAVA_OPTS="-Xms512m -Xmx512m" -p 9200:9200 -p 9300:9300 -v /elasticsearch6.7.1/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /elasticsearch6.7.1/data:/usr/share/elasticsearch/data elasticsearch:6.7.1
都成功了
带*的是主节点
安装elasticsearch-head插件:
docker pull mobz/elasticsearch-head:5
只需要在其中一台机器安装即可
安装完成执行命令
docker run -d -p 9100:9100 --name es-manager mobz/elasticsearch-head:5
整合SpringBoot:
application.yml: 只关注elasticsearch那部分即可
server:
port: 8081
# 下面是配置undertow作为服务器的参数
undertow:
# 设置IO线程数, 它主要执行非阻塞的任务,它们会负责多个连接, 默认设置每个CPU核心一个线程
io-threads: 4
# 阻塞任务线程池, 当执行类似servlet请求阻塞操作, undertow会从这个线程池中取得线程,它的值设置取决于系统的负载
worker-threads: 20
# 以下的配置会影响buffer,这些buffer会用于服务器连接的IO操作,有点类似netty的池化内存管理
# 每块buffer的空间大小,越小的空间被利用越充分
buffer-size: 1024
# 是否分配的直接内存
direct-buffers: true
#启用shutdown
#endpoints:
# shutdown:
# enable: true
#禁用密码验证
#endpoints:
#shutdown:
#sensitive: false
#linux关闭的脚本
#curl -X POST host:port/shutdown
#开启shutdown的安全验证
#endpoints:
#shutdown:
#sensitive: true
#验证用户名和密码
#security:
#user:
#name: admin
#password: admin
#角色
#management:
#address: 127.0.0.1
#port: 8081
#security:
#role: SUPERUSER
spring:
datasource:
type: com.alibaba.druid.pool.DruidDataSource
driverClassName: com.mysql.jdbc.Driver
driver-class-name: com.mysql.jdbc.Driver
platform: mysql
url: jdbc:mysql://120.79.81.103:5306/miniprogram?useUnicode=true&characterEncoding=UTF-8&allowMultiQueries=true&useSSL=false
username: root
password: admin
initialSize: 5
minIdle: 5
maxActive: 20
maxWait: 60000
timeBetweenEvictionRunsMillis: 60000
minEvictableIdleTimeMillis: 300000
validationQuery: SELECT1FROMDUAL
testWhileIdle: true
testOnBorrow: false
testOnReturn: false
filters: stat,wall
logSlowSql: true
# ELASTICSEARCH (ElasticsearchProperties)
# Elasticsearch cluster name.
data:
elasticsearch:
cluster-name: elasticsearch
cluster-nodes: 192.168.13.111:9300,192.168.13.222:9300
repositories:
enabled: true
redis:
database: 1
host: 211.149.199.68
port: 6379
password: ******
timeout: 10000
activemq:
queueName: mvp.queue
topicName: mvp.topic
#账号密码
user: user
password: user
#URL of the ActiveMQ broker.
broker-url: tcp://localhost:61616
in-memory: false
#必须使用连接池
pool:
#启用连接池
enabled: true
#连接池最大连接数
max-connections: 5
#空闲的连接过期时间,默认为30秒
idle-timeout: 30s
# jedis: 有默认值,源码:RedisProperties
# pool:
# max-active:
# max-idle:
# max-wait:
# min-idle:
mybatis:
typeAliasesPackage: com.pinyu.miniprogram.mysql.entity
mapper-locations: classpath:mapper/**/*Mapper.xml
mapper:
mappers: com.pinyu.miniprogram.mysql.mappers.BaseMapper
identity: mysql
#logging.config:
# classpath: test/log4j2_test.xml
IdEntity:
package com.pinyu.miniprogram.mysql.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import com.pinyu.miniprogram.mysql.entity.member.MemberEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author ypp 创建时间:2018年12月25日 下午1:32:18
* @Description: TODO(用一句话描述该文件做什么)
*/
@Data // getter、setter
@AllArgsConstructor // 全参构造方法
@NoArgsConstructor // 无参构造方法
@Accessors(chain = true) // 链式编程写法
public class IdEntity implements Serializable {
/**
*
*/
private static final long serialVersionUID = -9089706482760436909L;
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
@org.springframework.data.annotation.Id
private Long id;
}
@Id
@Column(name = "id")
@GeneratedValue(strategy = GenerationType.IDENTITY)
这3个注解是通用mapper的注解
@org.springframework.data.annotation.Id 这个注解才是elasticsearch的id注解
BaseEntity:
package com.pinyu.miniprogram.mysql.entity;
import java.util.Date;
import javax.persistence.Column;
import com.pinyu.miniprogram.mysql.entity.member.MemberEntity;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @author ypp 创建时间:2018年12月25日 下午1:32:28
* @Description: TODO(用一句话描述该文件做什么)
*/
@Data // getter、setter
@AllArgsConstructor // 全参构造方法
@NoArgsConstructor // 无参构造方法
@Accessors(chain = true) // 链式编程写法
public class BaseEntity extends IdEntity {
/**
*
*/
private static final long serialVersionUID = 8575696766261326260L;
@Column(name="creat_id")
private Integer creatId;
@Column(name="create_date")
private Date createDate;
@Column(name="delete_state")
private Integer deleteState;// 删除状态 1正常 2已删除
}
BaseEntity的字段没有用到,这是通用mapper设置的字段
BookEntity:
package com.pinyu.miniprogram.mysql.entity.book;
import org.springframework.data.elasticsearch.annotations.Document;
import com.pinyu.miniprogram.mysql.entity.BaseEntity;
import lombok.Data;
import lombok.experimental.Accessors;
@Data
@Accessors(chain=true)
@Document(indexName = "book", type = "_doc")
public class BookEntity extends BaseEntity{
private String title;
private String author;
private String postDate;
public BookEntity(Long id, String title,String author,String postDate){
setId(id);
this.title=title;
this.author=author;
this.postDate=postDate;
}
}
@Document(indexName = "book", type = "_doc")
Document表示elasticsearch的document,indexName索引名称 type就是elasticsearch的type
BookRepository:
package com.pinyu.miniprogram.mysql.repositry;
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import com.pinyu.miniprogram.mysql.entity.book.BookEntity;
public interface BookRepository extends ElasticsearchRepository<BookEntity,Long>{
Page<BookEntity> findByAuthor(String author, Pageable pageable);
Page<BookEntity> findByTitle(String title, Pageable pageable);
List<BookEntity> findByTitle(String title);
}
注意ElasticsearchRepository<BookEntity,Long> 里面的Long要和实体类型的id类型保持一致,不然要报错,类型转换异常
BookService:
package com.pinyu.miniprogram.mysql.service.book;
import java.util.List;
import java.util.Optional;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import com.pinyu.miniprogram.mysql.entity.book.BookEntity;
public interface BookService {
Optional<BookEntity> findById(Long id);
BookEntity save(BookEntity blog);
void delete(BookEntity blog);
Optional<BookEntity> findOne(Long id);
List<BookEntity> findAll();
Page<BookEntity> findByAuthor(String author, PageRequest pageRequest);
Page<BookEntity> findByTitle(String title, PageRequest pageRequest);
List<BookEntity> findTitle(String titileKeyword);
Iterable<BookEntity> saveAll(List<BookEntity> books);
}
BookServiceImpl:
package com.pinyu.miniprogram.mysql.service.book.impl;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;
import com.pinyu.miniprogram.mysql.entity.book.BookEntity;
import com.pinyu.miniprogram.mysql.repositry.BookRepository;
import com.pinyu.miniprogram.mysql.service.book.BookService;
@Service
public class BookServiceImpl implements BookService{
@Autowired
private BookRepository bookRepository;
@Override
public Optional<BookEntity> findById(Long id) {
//CrudRepository中的方法
return bookRepository.findById(id);
}
@Override
public BookEntity save(BookEntity blog) {
return bookRepository.save(blog);
}
@Override
public void delete(BookEntity blog) {
bookRepository.delete(blog);
}
@Override
public Optional<BookEntity> findOne(Long id) {
return bookRepository.findById(id);
}
@Override
public List<BookEntity> findAll() {
return (List<BookEntity>) bookRepository.findAll();
}
@Override
public Page<BookEntity> findByAuthor(String author, PageRequest pageRequest) {
return bookRepository.findByAuthor(author,pageRequest);
}
@Override
public Page<BookEntity> findByTitle(String title, PageRequest pageRequest) {
return bookRepository.findByTitle(title,pageRequest);
}
@Override
public List<BookEntity> findTitle(String titileKeyword) {
return bookRepository.findByTitle(titileKeyword);
}
@Override
public Iterable<BookEntity> saveAll(List<BookEntity> BookEntitys) {
return bookRepository.saveAll(BookEntitys);
}
}
BookController:
package com.pinyu.miniprogram.web.controller.book;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import com.pinyu.miniprogram.mysql.entity.book.BookEntity;
import com.pinyu.miniprogram.mysql.service.book.BookService;
@Controller
@RequestMapping("/es")
public class BookController {
@Autowired
private BookService bookService;
@RequestMapping("/book/{id}")
@ResponseBody
public BookEntity getBookEntityById(@PathVariable Long id){
Optional<BookEntity> opt =bookService.findById(id);
BookEntity book=opt.get();
System.out.println(book);
return book;
}
@RequestMapping("/save")
@ResponseBody
public void Save(){
BookEntity book1=new BookEntity(1L,"ES入门教程","ypp","2018-10-01");
BookEntity book2=new BookEntity(2L,"从ES入门教程到放弃java","ypp","2018-10-01");
BookEntity book3=new BookEntity(3L,"mysql从入门到放弃","ypp","2018-10-01");
BookEntity book4=new BookEntity(4L,"redis从入门到放弃","ypp","2018-10-01");
BookEntity book5=new BookEntity(5L,"spark从入门到放弃","ypp","2018-10-01");
BookEntity book6=new BookEntity(6L,"hbase从入门到放弃","ypp","2018-10-01");
BookEntity book7=new BookEntity(7L,"zookeeper从入门到放弃","ypp","2018-10-01");
BookEntity book8=new BookEntity(8L,"mq从入门到放弃","ypp","2018-10-01");
BookEntity book9=new BookEntity(9L,"spring cloud从入门到放弃","ypp","2018-10-01");
List<BookEntity> books=new ArrayList<>();
books.add(book1);
books.add(book2);
books.add(book3);
books.add(book4);
books.add(book5);
books.add(book6);
books.add(book7);
books.add(book8);
books.add(book9);
try {
bookService.saveAll(books);
} catch (Exception e) {
e.printStackTrace();
}
}
@RequestMapping("/keyword")
@ResponseBody
public List<BookEntity> keyword(@RequestParam("keyword")String keyword){
return bookService.findTitle(keyword);
}
}
发送save请求插入
插入成功,但是在head视图数据有错误,没有查询到
head视图插件里面的请求是失败的,单独拿出来浏览器访问时可以访问到索引数据,应该是哪里没有配置对。111/222浏览器访问都可以拿到,head里面的111/222都拿不到。能证明数据是插入到elasticsearch集群了。视图插件配置有误。请求406.其他是可以看到数据的,后面来修正
9条
至此SpringBoot整合elasticsearch集群算成功了