Elasticsearch 错误:None of the configured nodes are available

在使用 ElasticsearchTransportClient 的时候,遇到异常:None of the configured nodes are available,后来发现是 Elasticsearch 集群网络不稳定,通过增加请求重试次数的方式解决。本文涉及的开发环境:Elasticsearch v1.7.5

问题出现

本文中提及的 Elasticsearch 版本为 v1.7.5,是一个比较陈旧的版本,读者在阅读时可能会发现某些方法与高版本不一样,可以不用理会。

涉及到的业务场景很简单,就是使用 TransportClient 方式去连接 Elasticsearch 集群,然后发送请求、获取结果,解析结果后得到需要的数值。

在某一次常规的运行过程中,出现异常:

1
2
3
4
5
6
7
8
9
10
org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: []
at org.elasticsearch.client.transport.TransportClientNodesService.ensureNodesAreAvailable (TransportClientNodesService.java:305)
at org.elasticsearch.client.transport.TransportClientNodesService.execute (TransportClientNodesService.java:200)
at org.elasticsearch.client.transport.support.InternalTransportClient.execute (InternalTransportClient.java:106)
at org.elasticsearch.client.support.AbstractClient.search (AbstractClient.java:338)
at org.elasticsearch.client.transport.TransportClient.search (TransportClient.java:430)
at org.elasticsearch.action.search.SearchRequestBuilder.doExecute (SearchRequestBuilder.java:1112)
at org.elasticsearch.action.ActionRequestBuilder.execute (ActionRequestBuilder.java:91)
at org.elasticsearch.action.ActionRequestBuilder.execute (ActionRequestBuilder.java:65)
......

核心在于 NoNodeAvailableException: None of the configured nodes are available: [],无法获取可用的节点,说明无法连接上指定的主机。可能是主机 ip 指定错误,也可能是 Elasticsearch 集群故障,也可能是网络不好。

问题分析解决

如果上面的主机 ip 配置正确,就没问题,接着查看配置,是正确的。而且进一步考虑,并不是一开始运行就失败抛出异常,而是运行一段时间后才抛出异常,这可以说明网络环境,或者 Elasticsearch 集群偶然性有问题。

其中,生成 TransportClient 的代码如下,需要指定 ip、集群名称、其它多个参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/**
* 获取 Es TransportClient
*
* @param clusterName: 集群名
* @param hosts : IPs
* @return
*/
public static TransportClient getEsClient (String clusterName, String hosts) {
Settings settings = ImmutableSettings.settingsBuilder ()
.put ("cluster.name", clusterName)
.put ("client.transport.ping_timeout", "120s")
.put ("discovery.zen.fd.ping_retries", 5)
// 嗅探整个集群的状态,不用手动设置集群里所有集群的 ip 到连接客户端
.put ("client.transport.sniff", true)
.build ();
TransportClient client = new TransportClient (settings);
String [] host = hosts.split (",");
for (String h : host) {
String [] vals = h.split (":");
int port = vals.length > 1 ? Integer.parseint (vals [1]) : 9300;
client.addTransportAddress (new InetSocketTransportAddress (vals [0], port));
}
return client;
}

而在抛出异常的地方,代码为:

1
searchRequestBuilder.execute ().actionGet (new TimeValue (timeOutMinute * 60 * 1000))

其中,searchRequestBuilder 是请求构造器,包含索引名称、查询条件等信息,来自于 TransportClient 对象,代码如下:

1
2
3
4
5
6
//boolQueryBuilder 是查询条件对象 
SearchRequestBuilder searchRequestBuilder = client.prepareSearch (indexName)
.setTypes (indexType)
.clearRescorers ()
.setQuery (boolQueryBuilder)
.setSize (size);

以上,理清代码逻辑后,观察 Elasticsearch 集群的状态多次,没有发现异常,那就可能是网络问题了,准备在代码中加上请求重试机制。

searchRequestBuilder.execute () 抛出异常后等待 5 秒再次重试,最多重试 5 次。

再次运行程序,观察日志后,发现仍旧有部分请求会失败,但是由于有等待重试的逻辑,不会影响到业务结果。

这种偶尔的网络问题只能反馈给运维人员继续排查了。

虾丸派 wechat
扫一扫添加博主,进技术交流群,共同学习进步
永不止步
0%