CrazyAirhead

疯狂的傻瓜,傻瓜也疯狂——傻方能执著,疯狂才专注!

0%

client.transport.sniff配置引起的问题

问题

之前基于Docker搭建了ES环境,也能正常使用,这周突然程序能正常启动,但实际发生ES调用时出错,错误如下:

1
2
3
4
5
6
7
8
9
10
org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{zYhliWDFSRGpbaB371OV-g}{172.26.0.251}{172.26.0.251:9300}]
at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable(TransportClientNodesService.java:349)
at org.elasticsearch.client.transport.TransportClientNodesService.execute(TransportClientNodesService.java:247)
at org.elasticsearch.client.transport.TransportProxyClient.execute(TransportProxyClient.java:60)
at org.elasticsearch.client.transport.TransportClient.doExecute(TransportClient.java:381)
at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:407)
at org.elasticsearch.client.support.AbstractClient.execute(AbstractClient.java:396)
at org.elasticsearch.action.ActionRequestBuilder.execute(ActionRequestBuilder.java:46)
at org.elasticsearch.action.ActionRequestBuilder.get(ActionRequestBuilder.java:53)
...

现在将问题做下记录,主要是client.transport.sniff的使用问题。

环境

基于Docker的ES,官网

1
docker run -d --name elasticsearch -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" elasticsearch:6.5.4

客户端

客户端代码基本参照了ES官网

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@Bean(destroyMethod = "close")
public TransportClient client() throws Exception {
TransportClient client = new PreBuiltTransportClient(settings());

String clusterNodes = elasticsearchProperties.getClusterNodes();
Assert.hasText(clusterNodes, "[Assertion failed] clusterNodes settings missing.");

for (String clusterNode : split(clusterNodes, ElasticsearchProperties.COMMA)) {
String hostName = substringBeforeLast(clusterNode, ElasticsearchProperties.COLON);
String port = substringAfterLast(clusterNode, ElasticsearchProperties.COLON);
Assert.hasText(hostName, "[Assertion failed] missing host name in 'clusterNodes'");
Assert.hasText(port, "[Assertion failed] missing port in 'clusterNodes'");
logger.info("adding transport node : " + clusterNode);
client.addTransportAddress(new TransportAddress(InetAddress.getByName
(hostName), Integer.valueOf(port)));
}
client.connectedNodes();
return client;
}

private Settings settings() {
return Settings.builder()
.put("cluster.name", elasticsearchProperties.getClusterName())
.put("client.transport.sniff", elasticsearchProperties.getClientTransportSniff())
.put("client.transport.ignore_cluster_name", elasticsearchProperties
.getClientIgnoreClusterName())
.put("client.transport.ping_timeout", elasticsearchProperties
.getClientPingTimeout())
.put("client.transport.nodes_sampler_interval", elasticsearchProperties
.getClientNodesSamplerInterval())
.build();
}

问题处理

因为之前可以访问,例常的检查了cluster.name和配置的服务器和端口,一切正常。

经过一些搜索后发现这篇文章,NoNodeAvailableException,其中提到了配置了client.transport.snifftrue

检查代码,自己默认配置也是true。调整client.transport.snifffalse,一切正常了。

分析及处理

client.transport.sniff的作用是:使客户端去嗅探整个集群的状态,把集群中其它机器的ip地址加到客户端中。这样做的好处是,一般你不用手动设置集群里所有集群的ip到连接客户端,它会自动帮你添加,并且自动发现新加入集群的机器。

但使用该参数时有个注意事项。当ES服务器监听(publish_address )使用内网服务器IP,而访问(bound_addresses )使用外网IP时,不要设置client.transport.sniff为true。不设置client.transport.sniff时,默认为false(关闭客户端去嗅探整个集群的状态)。因为在自动发现时会使用内网IP进行通信,导致无法连接到ES服务器。因此此时需要直接使用addTransportAddress方法把集群中其它机器的ip地址加到客户端中。
然后检查了下Docker的启动日志:

1
2
3
4
[2019-04-16T05:45:56,427][INFO ][o.e.n.Node               ] [ehrCloud] starting ...
[2019-04-16T05:45:56,648][INFO ][o.e.t.TransportService ] [ehrCloud] publish_address {172.17.0.3:9300}, bound_addresses {0.0.0.0:9300}
[2019-04-16T05:45:56,796][INFO ][o.e.x.s.t.n.SecurityNetty4HttpServerTransport] [ehrCloud] publish_address {172.17.0.3:9200}, bound_addresses {0.0.0.0:9200}
[2019-04-16T05:45:56,797][INFO ][o.e.n.Node ] [ehrCloud] started

之后做了如下尝试,修改配置:

1
network.public_host: 172.26.0.251

重新运行程序,此时无论client.transport.sniff的配置为何,都可正常使用。

不过为什么之前可以,现在不行这个问题还是不清楚。

参考链接

ES版本问题

elasticsearch中client.transport.sniff的使用方法和注意事项

欢迎关注我的其它发布渠道