1、創(chuàng)建一個node,加入集群中,通過這個node獲得client。
2、通過TransportClient來連接集群。
第一種方式,相當(dāng)于額外啟動了一個es的node節(jié)點,只是這個node是由我們編碼控制的,可以設(shè)置成這個node是不存數(shù)據(jù)的節(jié)點(沒有特殊原因你就應(yīng)該這么設(shè)置),這個節(jié)點的配置和其他的節(jié)點沒有什么區(qū)別,也是通過elasticsearch.yml文件來配置,配置文件放在classpath目錄下面,當(dāng)然你也可以通過編程的方式,在構(gòu)建node的時候,設(shè)置settings參數(shù)。
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();
第二種方法,相當(dāng)于獲取了所有node節(jié)點的client,發(fā)送請求的時候遍歷當(dāng)前可用的client(這里可用指的是可以連接,但是node本身不一定可用,比如node正在恢復(fù)中,還沒有加入集群,這會產(chǎn)生問題,見下面)。跟方法一相比,方法二會產(chǎn)生雙跳(double hop),即當(dāng)前遍歷到node1,但訪問的數(shù)據(jù)在node2,請求先發(fā)到node1,又由node1轉(zhuǎn)發(fā)到node2。
遍歷方式:每次請求通過AtomicInteger進行原子加1(超出最大值后設(shè)置成0),按當(dāng)前可用client數(shù)取模。
獲取當(dāng)前可用client的方法:使用線程池,遍歷所有client,如果client未連接,嘗試一次連接,連接成功加入可用client中,如果client已連接直接加入可用client。
可以通過設(shè)置參數(shù)client.transport.sniff是否為true,來設(shè)置是使用SimpleNodeSampler還是SniffNodesSampler,默認(rèn)值為false,即使用SimpleNodeSampler。
具體實現(xiàn)在org.elasticsearch.client.transport.TransportClientNodesService類中。
簡單的說,SimpleNodeSampler會限制當(dāng)前可用client一定是在配置中設(shè)置的節(jié)點中的,而SniffNodesSampler會使用所有發(fā)現(xiàn)的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)); }
方法二有個問題,就是當(dāng)集群中某個node掛掉之后,重新加入的時候,因為是通過判斷client是否可以連接,而不是node是否可用,這會導(dǎo)致這個時候使用這個client發(fā)送請求的時候產(chǎn)生異常。而方法一不會,因為還沒加入集群的node,對于自己創(chuàng)建的node來說是不可見的。gitbub上有對這個問題的討論: