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(嗅探器)

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,并且可以设置请求超时时间,避免因为拉取节点时间过长,影响服务恢复的速度或恢复失败,尽管设置超时时间后可能获得的节点数少于集群中的节点数

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| NodesSniffer nodesSniffer = ``new ElasticsearchNodesSniffer( ``restClient, ``TimeUnit.SECONDS.toMillis(``5``), ``// 默认ElasticsearchNodesSniffer.DEFAULT_SNIFF_REQUEST_TIMEOUT ``ElasticsearchNodesSniffer.Scheme.HTTPS); ``// 若是HTTP协议,则ElasticsearchNodesSniffer.Scheme.HTTP Sniffer sniffer = Sniffer.builder(client) ``.setNodesSniffer(nodesSniffer).build(); |

也可以自定义获取节点的方法,进而可以获取其他ElasticSearch数据源或做一些其他的扩展,如下所示

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| NodesSniffer nodesSniffer = ``new NodesSniffer() { ``@Override ``public List<Node> sniff() ``throws IOException { ``// 自行按需实现获取节点的逻辑 ``return null``; ``} }; Sniffer sniffer = Sniffer.builder(client) ``.setNodesSniffer(nodesSniffer).build(); |

相关推荐
RainbowSea11 分钟前
补充:问题:CORS ,前后端访问跨域问题
java·spring boot·spring
RainbowSea13 分钟前
15. MySQL 多版本并发控制
java·sql·mysql
倔强的石头10621 分钟前
飞算JavaAI:重构软件开发范式的智能引擎
java·数据库·重构
Q_9709563937 分钟前
java+vue+SpringBoo足球社区管理系统(程序+数据库+报告+部署教程+答辩指导)
java·开发语言·数据库
要开心吖ZSH42 分钟前
微服务架构的演进:迈向云原生
java·微服务·云原生
为了更好的明天而战1 小时前
Java 中的 ArrayList 和 LinkedList 区别详解(源码级理解)
java·开发语言
小袁拒绝摆烂1 小时前
ElasticSearch快速入门-1
大数据·elasticsearch·搜索引擎
JosieBook1 小时前
【Java编程动手学】Java中的数组与集合
java·开发语言·python
N_NAN_N2 小时前
类图+案例+代码详解:软件设计模式----单例模式
java·单例模式·设计模式
weixin_399380692 小时前
k8s一键部署tongweb企业版7049m6(by why+lqw)
java·linux·运维·服务器·云原生·容器·kubernetes