docker搭建elasticsearch集群及集成spring boot

Elasticsearch

elasticsearch集群搭建

elasticsearch集群使用docker 搭建

1.修改系统配置文件
#修改线程数
#单个进程中的最大线程数
vim /etc/sysctl.conf
vm.max_map_count=262144
# 刷新配置 使其立即生效配置
2.创建elasticsearch配置文件

创建三个节点,即三个文件夹都放入elasticsearch.yml ;jvm.options配置文件

elasticsearch配置文件elasticsearch.yml参数详细说明

/wz/elasticsearch/es-cluster/node01
/wz/elasticsearch/es-cluster/node02/data2
/wz/elasticsearch/es-cluster/node03
#顺便都创建一个data文件夹存放elasticsearch的数据
madir /wz/elasticsearch/es-cluster/node01/data1
madir /wz/elasticsearch/es-cluster/node01/data1
madir /wz/elasticsearch/es-cluster/node01/data1

在各个文件夹下放入对应的elasticsearch.yml ;jvm.options 文件

node1配置
cd /wz/elasticsearch/es-cluster/node01
vim elasticsearch.yml
# node1(master) 的yml配置文件
cluster.name: es-tanhua-cluster #集群名称,相同网络下相同的集群名的节点为一个集群
node.name: es-node01 #节点名称,若未指定,将随机分配
#cluster.initial_master_nodes: es-node1
network.bind_host: 0.0.0.0 #设置绑定的ip地址,可以是ipv4或ipv6的,默认为0.0.0.0。
network.publish_host: 自己的ip  #设置与其他节点通信的地址,如果不指定,其将自动生成.这个地址必须是实际的IP地址
node.master: true #是否指定当前节点为master节点
transport.tcp.port: 9301 #端口
node.data: true #是否允许该节 点存储数据
network.host: 自己的ip   #这个参数是用来同时设置bind_host和publish_host上面两个参数。
http.port: 9201 #设置对外服务的http端口,默认为9200
discovery.zen.ping.unicast.hosts: ["ip"] #设置集群中master节点的初始列表,可以通过这些节点来自动发现新加入集群的节点。
discovery.zen.minimum_master_nodes: 2 #设置这个参数来保证集群中的节点可以知道其它N个有master资格的节点。默认为1,对于大的集群来说,可以设置大一点的值(2-4)
http.cors.enabled: true
http.cors.allow-origin: "*"

jvm.options

-Xms129m
-Xmx128m
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+AlwaysPreTouch
-Xss1m
-Djava.awt.headless=true
-Dfile.encoding=UTF-8
-Djna.nosys=true
-XX:-OmitStackTraceInFastThrow
-Dio.netty.noUnsafe=true
-Dio.netty.noKeySetOptimization=true
-Dio.netty.recycler.maxCapacityPerThread=0
-Dlog4j.shutdownHookEnabled=false
-Dlog4j2.disable.jmx=true
-Djava.io.tmpdir=${ES_TMPDIR}
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
-XX:ErrorFile=logs/hs_err_pid%p.log
8:-XX:+PrintGCDetails
8:-XX:+PrintGCDateStamps
8:-XX:+PrintTenuringDistribution
8:-XX:+PrintGCApplicationStoppedTime
8:-Xloggc:logs/gc.log
8:-XX:+UseGCLogFileRotation
8:-XX:NumberOfGCLogFiles=32

node1节点完成

在这里插入图片描述

node2,node3 节点步骤同上 但是elasticsearch.yml 配置文件不同

node2配置

node2.elasticsearch.yml

cluster.name: es-tanhua-cluster
node.name: es-node02
# cluster.initial_master_nodes: es-node1
network.bind_host: 0.0.0.0
transport.tcp.port: 9302
node.master: true
node.data: true
network.host: 自己的ip
http.port: 9202
discovery.zen.ping.unicast.hosts: ["masterIp"]
discovery.zen.minimum_master_nodes: 2
http.cors.enabled: true
http.cors.allow-origin: "*"
node.max_local_storage_nodes: 256

jvm.options

-Xms129m
-Xmx128m
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+AlwaysPreTouch
-Xss1m
-Djava.awt.headless=true
-Dfile.encoding=UTF-8
-Djna.nosys=true
-XX:-OmitStackTraceInFastThrow
-Dio.netty.noUnsafe=true
-Dio.netty.noKeySetOptimization=true
-Dio.netty.recycler.maxCapacityPerThread=0
-Dlog4j.shutdownHookEnabled=false
-Dlog4j2.disable.jmx=true
-Djava.io.tmpdir=${ES_TMPDIR}
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
-XX:ErrorFile=logs/hs_err_pid%p.log
8:-XX:+PrintGCDetails
8:-XX:+PrintGCDateStamps
8:-XX:+PrintTenuringDistribution
8:-XX:+PrintGCApplicationStoppedTime
8:-Xloggc:logs/gc.log
8:-XX:+UseGCLogFileRotation
8:-XX:NumberOfGCLogFiles=32
node3配置

node3.elasticsearch.yml

cluster.name: es-tanhua-cluster
#cluster.initial_master_nodes: es-node1
node.name: es-node03
node.master: true
node.data: true
network.bind_host: 0.0.0.0
network.host: 自己的ip
http.port: 9203
discovery.zen.ping.unicast.hosts: ["node1的ip:9301","node2的ip:9302","node3的ip:9303"]
discovery.zen.minimum_master_nodes: 2
http.cors.enabled: true
http.cors.allow-origin: "*"

jvm.options

-Xms129m
-Xmx128m
-XX:+UseConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=75
-XX:+UseCMSInitiatingOccupancyOnly
-XX:+AlwaysPreTouch
-Xss1m
-Djava.awt.headless=true
-Dfile.encoding=UTF-8
-Djna.nosys=true
-XX:-OmitStackTraceInFastThrow
-Dio.netty.noUnsafe=true
-Dio.netty.noKeySetOptimization=true
-Dio.netty.recycler.maxCapacityPerThread=0
-Dlog4j.shutdownHookEnabled=false
-Dlog4j2.disable.jmx=true
-Djava.io.tmpdir=${ES_TMPDIR}
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=data
-XX:ErrorFile=logs/hs_err_pid%p.log
8:-XX:+PrintGCDetails
8:-XX:+PrintGCDateStamps
8:-XX:+PrintTenuringDistribution
8:-XX:+PrintGCApplicationStoppedTime
8:-Xloggc:logs/gc.log
8:-XX:+UseGCLogFileRotation
8:-XX:NumberOfGCLogFiles=32

三个节点的配置配件准备完毕!

3.拉取docker elasticsearch镜像
# docker pull elasticsearch : 版本
docker pull elasticsearch : 6.5.4
# 查看
docker images

在这里插入图片描述

4.创建容器
#node1
docker create --name es-node01 --net host -v /wz/elasticsearch/es-cluster/node01/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /wz/elasticsearch/es-cluster/node01/jvm.options:/usr/share/elasticsearch/config/jvm.options -v /wz/elasticsearch/es-cluster/node01/data1:/usr/share/elasticsearch/data  elasticsearch:6.5.4

#node2
docker create --name es-node02 --net host -v /wz/elasticsearch/es-cluster/node02/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /wz/elasticsearch/es-cluster/node02/jvm.options:/usr/share/elasticsearch/config/jvm.options -v /wz/elasticsearch/es-cluster/node02/data2:/usr/share/elasticsearch/data elasticsearch:6.5.4

#node3
docker create --name es-node03 --net host -v /wz/elasticsearch/es-cluster/node03/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml -v /wz/elasticsearch/es-cluster/node03/jvm.options:/usr/share/elasticsearch/config/jvm.options -v /wz/elasticsearch/es-cluster/node03/data3:/usr/share/elasticsearch/data elasticsearch:6.5.4
docker 挂载参数解释
docker create --name 容器名 --net host -v 配置文件elasticsearch.yml的地址:/usr/share/elasticsearch/config/elasticsearch.yml -v  jvm.options文件的地址:/usr/share/elasticsearch/config/jvm.options -v 数据存放data文件夹地址:/usr/share/elasticsearch/data  拉取的elasticsearch及版本(如果多个不同版本的elasticsearch可以用image id代替)
5.启动容器

集群启动

#三个节点一起启动容器
docker start es-node01 es-node02 es-node03
# 查看容器日志 
#docker logs 容器名/imges id
docker logs es-node1

单节点启动

#或单个启动并查看日志
docker start es-node01 && docker logs -f es-node01
docker start es-node02 && docker logs -f es-node02
docker start es-node03 && docker logs -f es-node03
6.验证
1.查看 elasticsearch 各个节点

elasticsearch进行外部访问的端口为 92xx(自己在elasticsearch.yml绑定的)没有默认为 9200,elasticsearch内部通信的端口为:93xx (自己在elasticsearch.yml绑定的)没有默认为 9300可以在浏览器上各个节点进行ip+端口(92xx的端口)进行访问

在这里插入图片描述

验证elasticsearch集群,在浏览器输入http://es ip地址:端口/_cat/nodes?pretty,就可以看到集群启动成功了:

例如:http://192.168.2.223:9202/_cat/nodes?pretty

无论集群的哪个几点下访问都行,如图:

在这里插入图片描述

如果如上图则elasticsearch集群搭建完毕!

elasticsearch集成spring boot

1.添加依赖

注意:elasticsearch 的版本要和spring boot 保持一致 推荐使用maven给的版本,冲突几率小

如果是项目中 还集成了 redis 三者(elasticsearch,boot ,redsi)应保持同一版本

  <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
   </dependency>

2.配置yml

data:
  elasticsearch:
    cluster-name: es-tanhua-cluster #elasticsearch集群名
    cluster-nodes: 1.15.134.32:9301,1.15.134.32:9302,1.15.134.32:9303 #elasticsearch集群各个节点
  
  repositories:
     enabled: false #是否本地存储数据

3.使用

实体类使用
在这里插入图片描述

service 使用

@Slf4j
@Service(version = "2.6.4",interfaceClass = UserLocationApi.class)
public class UserLocationApiImpl implements UserLocationApi {

    @Autowired
    private ElasticsearchTemplate elasticsearchTemplate;

    //初始化索引库
    @PostConstruct
    public void initIndex() {
      //  System.setProperty("es.set.netty.runtime.available.processors","false");
        String indexName = "tanhua";
        //判断索引库是否存在
    //    boolean b = this.elasticsearchTemplate.indexExists(indexName);
       // System.out.println(b);
        if (!this.elasticsearchTemplate.indexExists(indexName)) {
            this.elasticsearchTemplate.createIndex(UserLocation.class);
        }
   //     boolean user_location = this.elasticsearchTemplate.typeExists(indexName, "user_location");
     //   System.out.println(user_location);
        //判断表是否存在  如果不存在 则创建
        if (!this.elasticsearchTemplate.typeExists(indexName, "user_location")) {
            this.elasticsearchTemplate.putMapping(UserLocation.class);

        }


    }

    /**
     * 更新地理位置
     *
     * @param userId    用户id
     * @param longitude 经度
     * @param latitude  纬度
     * @param address   地址名称
     * @return
     */
    @Override
    public Boolean updateUserLocation(Long userId, Double longitude, Double latitude, String address) {
        //首先根据id查询个人地理位置
        GetQuery getQuery = new GetQuery();
        getQuery.setId(Convert.toStr(userId));
        UserLocation userLocation = this.elasticsearchTemplate.queryForObject(getQuery, UserLocation.class);
       //如果不存在则添加 存在则更新
        if (ObjectUtil.isEmpty(userLocation)) {
            userLocation = new UserLocation();
            userLocation.setUserId(userId);
            userLocation.setAddress(address);
            userLocation.setLocation(new GeoPoint(latitude, longitude));
            userLocation.setCreated(System.currentTimeMillis());
            userLocation.setUpdated(userLocation.getCreated());
            userLocation.setLastUpdated(userLocation.getCreated());
            return this.saveUserLocation(userLocation);
        }else {
            //更新数据
            userLocation.setLocation(new GeoPoint(latitude, longitude));
            userLocation.setAddress(address);
            return this.updateLocation(userLocation); //更新

        }
    }

    public boolean saveUserLocation(UserLocation user) {
        IndexQuery indexQuery = new IndexQueryBuilder().withObject(user).build();

        //保存数据到ES中
        String index = this.elasticsearchTemplate.index(indexQuery);
        if (ObjectUtil.isEmpty(index)) return false;
        return true;

    }

    public boolean updateLocation(UserLocation user) {
        if (ObjectUtil.isEmpty(user))return false;

            HashMap<String, Object> map = new HashMap<>();
            //更新的字段
            map.put("location", user.getLocation());
            map.put("updated", System.currentTimeMillis());
            map.put("lastUpdated", user.getUpdated());
            map.put("address", user.getAddress());
        try {
            UpdateRequest request = new UpdateRequest();
            request.doc(map);
            UpdateQuery query = new UpdateQueryBuilder().withId(Convert.toStr(user.getUserId())).withClass(UserLocation.class).withUpdateRequest(request).build();

            //更新数据
            this.elasticsearchTemplate.update(query);
        } catch (Exception e) {
            log.error("更新地理位置失败~ userId = " + user.getUserId() + ", longitude = " + user.getLocation().getLon() + ", latitude = " + user.getLocation().getLat() + ", address = " + user.getAddress(), e);
            return false;
        }

        return true;
    }
}

测试
@RunWith(SpringRunner.class)
@SpringBootTest
public class testES {
 
    @Autowired
    private UserLocationApiImpl userLocationApi;
// 单元测试需要加这个  原因:在下面不加会报错
    public testES() {
        System.setProperty("es.set.netty.runtime.available.processors", "false");
    }

    @Test
    public void testUpdateUserLocation() {
        Boolean aa = this.userLocationApi.updateUserLocation(1L, 121.512253, 31.24094, "金茂大厦");
        System.out.println(aa);   
 
    }


}

elasticsearch添加会返回一个id 可以访问查看

打开浏览器: http://自己的ip:端口/分区/类型/id

例如:http://192.168.2.32:9201/tanhua/user_location/1

在这里插入图片描述

4.可能遇到的错误

4.1创建elasticsearchClient bean失败

报错为:org.springframework.beans.factory.BeanCreationException: Error creating bean with name ‘elasticsearchClient’ defined in class path resource [org/springframework/boot/autoconfigure/data/elasticsearch/ElasticsearchAutoConfiguration.class]: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.elasticsearch.client.transport.TransportClient]: Factory method ‘elasticsearchClient’ threw exception; nested exception is java.lang.IllegalStateException: availableProcessors is already set to [12], rejecting [12]
原因好像是 es 内置的netty冲突和redis内置的netty版本冲突导致,建议尽量版本保持一致由maven管理

解决方案:

  1. 创建一个配置类:

     
    
    import org.springframework.context.annotation.Configuration;
    
    import javax.annotation.PostConstruct;
    
    @Configuration
    public class ESconfig {
    
    
        @PostConstruct // @PostConstruct是Java自带的注解,在方法上加该注解会在项目启动的时候执行该方法,也可以理解为在spring容器初始化的时候执行该方法。
        void init() {
       // 不要查es 的netty     System.setProperty("es.set.netty.runtime.available.processors", "false");
        }
    }
    
    
    
  2. 启动类上加

// @EnableDubbo
@SpringBootApplication//(exclude = {MongoAutoConfiguration.class, MongoDataAutoConfiguration.class}) //排除mongo的自动配置
public class ESApplication {

    public static void main(String[] args) {
       //不要查es 的netty 
       System.setProperty("es.set.netty.runtime.available.processors","false");
        SpringApplication.run(ESApplication.class, args);


    }

}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值