Java连接elasticsearch有两种方式
- 创建一个node来加入集群,通过node获取client。
- 通过TransportClient来连接集群。
通过第一种来连接elasticsearch相当于在自己本机上又启动了一个es的node节点,这个节点是我们通过代码来控制,我们没什么特殊原因的情况下就应该吧这个节点设置为不存在的,这个节点的配置也是通过elasticsearch.xml配置,也可以在创建的时候设置node参数。
Setting setting = ImmutableSettings.settingBuilder().put("client.transport.ping_timeout",1000)
.put("timeout",1)
.putArray("discovery.zen.ping.unicast.hosts", "l-flightdev18.f.dev.cn0.qunar.com:9300", "l-flightdev17.f.dev.cn0.qunar.com:9300")
.build();
通过第二种方法连接es的时候相当于得到了所有node节点的client,发送请求的时候就可以遍历当前可用的client。
会产生双跳,例如当前遍历到node1,但是要访问的数据在node2,这样请求会先发到node1,然后node1转发到node2.
遍历的方式:每次请求通过AtomicInteger进行原子加1(超出最大值设为0)。
获取当前可用client的方式:使用线程池来遍历所有的client,如果client没有连接,那么就尝试一次连接,连接成功就可加入可用的client中,如果client已连接那么直接加入可用的client。
可以通过设置蚕食clent.transport.sniff是否为true,来设置是用simpleNodeSample还是SniffNodesSamler(默认是false),即SimpleNodeSample。
SimpleNodeSampler会限制当前空client一定在配置中设置的节点中,而SniffNodesSampler会使用所有发现的client,即使这个client的node不在配置中也会去使用。
Settings settings = ImmutableSettings.settingsBuilder() .put("client.transport.sniff", true)
.put("cluster.name", ES_CLUSTER_NAME).build();
TransportClient client= new TransportClient(settings);
for (String cluster : StringUtils.split(clusters,",")) {
client.addTransportAddress(new InetSocketTransportAddress("host1", 9300))
.addTransportAddress(new InetSocketTransportAddress("host2", 9300));
}
方法二有个问题,就是当集群中某个node挂掉之后,重新加入的时候,因为是通过判断client是否可以连接,而不是node是否可用,这会导致这个时候使用这个client发送请求的时候产生异常。而方法一不会,因为还没加入集群的node,对于自己创建的node来说是不可见的。gitbub上有对这个问题的讨论:https://github.com/elastic/elasticsearch/issues/11202