No Elasticsearch Node Available for olivere/elastic
前言
最近笔者接到了公司内部的ES团队的通知,需要将自己应用的数据从ES5搬迁到ES7。我在维护一个基于Golang语言开发的项目,遇到了一些关于ES 的Golang Client https://github.com/olivere/elastic 的问题,特此写这篇博客记录一下。
具体任务
在从ES5迁移到ES7的过程中,由于ES的换代的一些新特性和改变,需要首先进行具体任务的分解,主要包括
- 数据格式升级:从ES6开始,ES便不推荐在同一个Index下存在多个type的数据。因此需要将此前在同一个Index下数据拆散到不同的Index之中就可以解决问题(官方原因是之前index下不同实体太多,切分布稀疏不均匀,严重干扰 Lucene 压缩文档的能力,具体可参考 Removal of mapping types)
- ES client(olivere/elastic)的升级:由于底层已经切换到了最新的ES7,并且在我司内部的ES7 将强制启动token认证,同时由于采用了 ES的client olivere/elastic 所以需要选择最合适的方案进行代码的迁移。
“No Elasticsearch Node Available”
首先为了改最少的代码,笔者的第一个想法便是用olivere的ES5的client elastic.v5 直接访问最新的ES Endpoint,结果第一个遇到的问题便是"No Elasticsearch Node Available"。在经过Google一番之后, 从这篇博客中 程序印象 ,查出初步的主要原因是Sniffing的配置造成的。
Elasticsearch:Sniffing
Sniffing 的主要功能是将Elasticsearch的静态节点列表传递给客户端,然后将客户端请求平均分布在Elasticsearch 集群节点之间.如果启用 sniffing,则客户端将开始调用 _nodes /_all /http
端点(类似 http://127.0.0.1:9200/__nodes /_all /http
),并且响应将是群集中存在的所有节点及其 IP 地址的列表。然后,客户端将更新其连接池以使用所有新节点,并使群集状态与客户端的连接池保持同步。
如果想要检查自己的ES集群的Sniffing的配置,可以通过访问
curl -XGET 'http://127.0.0.1:9200/_nodes/http?pretty=true
{
"_nodes" : {
"total" : 1,
"successful" : 1,
"failed" : 0
},
"cluster_name" : "elasticsearch",
"nodes" : {
"v9vBH0xXQ1-GZw-bOfxlFQ" : {
"name" : "v9vBH0x",
"transport_address" : "127.0.0.1:9300",
"host" : "127.0.0.1",
"ip" : "127.0.0.1",
"version" : "7.2.1",
"build_hash" : "fe6cb20",
"roles" : [
"master",
"data",
"ingest"
],
"attributes" : {
"ml.max_open_jobs" : "10",
"ml.enabled" : "true"
},
"http" : {
"bound_address" : [
"0.0.0.0:9200"
],
"publish_address" : "127.0.0.1:9200", # sniffing mode setting
"max_content_length_in_bytes" : 104857600
}
}
}
}
如果想要在elastic.v5中禁止sniffing,在进行Client初始化的时候可以通过SetSniff(false)
来实现。
client, err := elastic.NewClient(elastic.SetURL(host), elastic.SetSniff(false))
但是在进行了上述的尝试之后,还是遇到了“No Elasticsearch Node Available”这个问题,证明Sniffing并不是链接不上ES7集群这个问题的主要原因。又经过了一番搜索之后, 查到了原因是 elastic.v5驱动的工作方式与 ES7配合的过程中存在某些问题,这个GitHub issue中则提供了进一步的分析。v5 connect panic: no Elasticsearch node available 。那么只能放弃使用elastic.v5的想法,将ES的Client升级到elastic.v7去。
总结
经过这次踩的坑,个人觉得对ES进行CRUD最好的方式还是用原生的HTTP请求便可,这样子下一次升级的时候只需要将ES的endpoint 切换一下便可,省去了才不同版本之间的Library切换所需要的时间和精力。