Java连接ElasticSearch详解

原创
2016/03/15 17:54
阅读数 8.1K

Java连接ES有两种连接方式(即获得ES的Client)

1、创建一个node,加入集群中,通过这个node获得client。

2、通过TransportClient来连接集群。

区别

第一种方式,相当于额外启动了一个es的node节点,只是这个node是由我们编码控制的,可以设置成这个node是不存数据的节点(没有特殊原因你就应该这么设置),这个节点的配置和其他的节点没有什么区别,也是通过elasticsearch.yml文件来配置,配置文件放在classpath目录下面,当然你也可以通过编程的方式,在构建node的时候,设置settings参数。

Settings settings = ImmutableSettings.settingsBuilder().put("client.transport.ping_timeout", 1000)
                .put("discovery.zen.ping.multicast.enabled", "false").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();
        Node node = NodeBuilder.nodeBuilder().clusterName("flight_fuwu_order_index").client(true).settings(settings).node();
        Client client = node.client();

注意:client(true)很重要,这标示当前节点不存储数据

方法一有个问题,如果服务和ES集群不在一个机房,网络延迟会导致作为node节点接入ES集群的服务成为ES集群的短板

 

第二种方法,相当于获取了所有node节点的client,发送请求的时候遍历当前可用的client(这里可用指的是可以连接,但是node本身不一定可用,比如node正在恢复中,还没有加入集群,这会产生问题,见下面)。跟方法一相比,方法二会产生双跳(double hop),即当前遍历到node1,但访问的数据在node2,请求先发到node1,又由node1转发到node2。

遍历方式:每次请求通过AtomicInteger进行原子加1(超出最大值后设置成0),按当前可用client数取模。

获取当前可用client的方法:使用线程池,遍历所有client,如果client未连接,尝试一次连接,连接成功加入可用client中,如果client已连接直接加入可用client。

可以通过设置参数client.transport.sniff是否为true,来设置是使用SimpleNodeSampler还是SniffNodesSampler,默认值为false,即使用SimpleNodeSampler。

具体实现在org.elasticsearch.client.transport.TransportClientNodesService类中。

简单的说,SimpleNodeSampler会限制当前可用client一定是在配置中设置的节点中的,而SniffNodesSampler会使用所有发现的client,即使这个client的node,不在配置中。

Settings settings = ImmutableSettings.settingsBuilder().put("cluster.name", clustersName).put(				"client.transport.ping_timeout", 1000).put("discovery.zen.ping.multicast.enabled", "false").put(				"timeout", 1)//				.put("client.transport.sniff", true)				.build();

		TransportClient transportClient = new TransportClient(settings);		for (String cluster : StringUtils.split(clusters,",")) {
			transportClient.addTransportAddress(new InetSocketTransportAddress("host1", 9300))
        .addTransportAddress(new InetSocketTransportAddress("host2", 9300));
		}

方法二有个问题,就是当集群中某个node挂掉之后,重新加入的时候,因为是通过判断client是否可以连接,而不是node是否可用,这会导致这个时候使用这个client发送请求的时候产生异常。而方法一不会,因为还没加入集群的node,对于自己创建的node来说是不可见的。gitbub上有对这个问题的讨论:https://github.com/elastic/elasticsearch/issues/11202

 

展开阅读全文
打赏
2
10 收藏
分享
加载中
更多评论
打赏
0 评论
10 收藏
2
分享
返回顶部
顶部