ElasticSearch的RestClient结合Sniffer提高可用性-一、背景">一、背景
由于要安装分词器插件,所以需要重启ElasticSearch集群以使得新安装的插件生效
但是在重启集群的过程中,服务端代码却出现了大量错误,如下所示
java.net.ConnectException: Connection refused at org.elasticsearch.client.RestClient.extractAndWrapCause(RestClient.java: 823 ) at org.elasticsearch.client.RestClient.performRequest(RestClient.java: 248 ) at org.elasticsearch.client.RestClient.performRequest(RestClient.java: 235 ) ...... |
基于此,也引出一个潜在的可用性问题,即代码没有做到可以平稳支持ElasticSearch集群的重启,不局限于可预知的升级导致的重启,包括集群自身不稳定导致的集群节点变化如某节点的CPU和内容过高、所在机柜或机房故障等不可预期情况
为了提高服务的可用性和稳定性,引入Sniffer(嗅探器)
Sniffer
允许从正在运行的 Elasticsearch 集群中自动发现节点并将它们设置为现有 RestClient 实例的最小库,默认使用节点信息API检索所属集群的交节点,并使用jackson解析得到json数据,与ElasticSearch 2.X及之后版本兼容。
添加Maven依赖以引入Sniffer,如下所示
< dependency > < groupId >org.elasticsearch.client</ groupId > < artifactId >elasticsearch-rest-client-sniffer</ artifactId > < version >7.6.2</ version > </ dependency > |
Sniffer相关的JavaDoc可参看:elasticsearch-rest-client-sniffer,代码如下所示
// 失败嗅探监听器,可保证在RestClient出现失败时,立即更新集群的节点 SniffOnFailureListener sniffOnFailureListener = new SniffOnFailureListener(); HttpHost httpHost = port != null ? new HttpHost(host, port, scheme) : HttpHost.create(host); RestClient client = RestClient.builder(httpHost) .setFailureListener(sniffOnFailureListener) .build(); Sniffer sniffer = Sniffer.builder(client) // 3 minutes, default 5 minutes,定时更新集群的节点 .setSniffIntervalMillis( 3 * 60 * 1000 ) // 30 seconds, default 1 minutes ,在失败立即更新集群的节点后,额外再次执行一次主动的更新行为 // 因为这个时间段内之前出问题的节点可能已经恢复,进而可以被再次更新到节点中被使用) .setSniffAfterFailureDelayMillis( 30 * 1000 ) .build(); sniffOnFailureListener.setSniffer(sniffer); |
需要注意的是,需要保证Sniffer和RestClient要具有相同的生命周期,并且应该先于RestClient关闭,如下所示
sniffer.close(); client.close(); |
也可通过以下方式更改是通过HTTP还是HTTPS,并且可以设置请求超时时间,避免因为拉取节点时间过长,影响服务恢复的速度或恢复失败,尽管设置超时时间后可能获得的节点数少于集群中的节点数
也可以自定义获取节点的方法,进而可以获取其他ElasticSearch数据源或做一些其他的扩展,如下所示