使用ElasticSearch的负载均衡器是不必要的?
我有一个在AWS EC2上运行的3个ElasticSearch节点集群。 这些节点使用OpsWorks / Chef进行设置。 我的目的是devise这个集群是非常有弹性和弹性的(节点可以在需要时进出)。
从我读过的有关ElasticSearch的一切,似乎没有人推荐将负载均衡器放在集群前面; 相反,似乎build议做两件事之一:
-
将您的客户端指向一个节点的URL / IP,让ES为您做负载平衡,并希望节点永不停机。
-
将所有节点的URL / IP硬编码到客户端应用程序中,让应用程序处理故障切换逻辑。
我的背景主要是在Web农场,创build一个巨大的自治Web服务器池,在它们前面放置一个ELB,并让负载平衡器决定哪些节点是活着或死亡是常识。 为什么ES似乎不支持这个相同的架构?
您不需要负载平衡器 – ES已经提供了该function。 你只是另一个组件,这可能会导致错误,并会增加一个不必要的networking跳跃。
ES会将你的数据分割(默认为5个分片),它将尝试在你的实例中均匀分配。 在你的情况下,2个实例应该有2个碎片,1个只有一个,但是你可能需要将碎片更改为6,以便平均分配。
默认情况下,复制设置为"number_of_replicas":1
,因此每个分片的一个副本。 假设你正在使用6个碎片,它可能看起来像这样(R是一个复制的碎片):
- node0:1,4,R3,R6
- node1:2,6,R1,R5
- 节点2:3,5,R2,R4
假设节点1死亡,群集将更改为以下设置:
- node0:1,4,6,R3 +新副本R5,R2
- 节点2:3,5,2,R4 +新副本R1,R6
根据您的连接设置,您可以连接到一个实例(传输客户端),也可以join群集(节点客户端)。 通过节点客户端,您将避免双跳,因为您将始终连接到正确的分片/索引。 使用传输客户端,您的请求将被路由到正确的实例。
所以没有什么可以为你自己负载平衡,你只是增加开销。 自动集群可能是ES最大的优势。
我相信对Elasticsearch集群进行负载平衡是一个好主意(devise一个容错系统,能够抵御单节点故障)。
为了构build您的集群,您需要有关Elasticsearch的两个主要function的背景:1.编写和更新文档和2.查询文档。
在elasticsearch中编写/索引文档:
- 当一个新文档进入Elasticsearch进行索引时,Elasticsearch使用“Shard Routing Algorithm”确定文档应该分配给的“主分片”
- 与分片关联的Lucene进程“映射”文档中的字段;
- Lucene进程将文档添加到碎片的Lucene“倒排索引”
- 任何“副本分片”然后接收文档; 副本分片“映射”文档并将文档添加到副本分片的Lucene“倒排索引”
在Elasticsearch中查询文档:
- 默认情况下,当查询发送到Elasticsearch时,查询命中一个节点 – 这成为查询的“查询节点”或“网关查询节点”
- 节点将查询广播到索引中的每个分片(主副本)
- 每个分片在分片的本地Lucene倒排索引上执行查询。
- 每个分片将前10-20个结果返回到“网关查询节点”
- “网关查询节点”然后对从其他分片返回的组合结果执行合并分类,
- 一旦合并分类完成,“网关查询节点”并返回结果给客户端
- 合并sorting是CPU和内存资源沉重
为写入/索引/更新构build负载平衡器
Elasticsearch自我pipe理节点上的碎片的位置。 “主节点”保持并更新“分片路由表”。 “主节点”将分片路由表的副本提供给集群中的其他节点。
通常,您不希望主节点对集群和更新路由表进行健康状况检查,并pipe理分片。
将负载平衡器指向“数据节点”(数据节点是包含data = shards的节点)并让数据节点使用其分片路由表来获取正确的分片写入可能是最好的。
架构查询
Elasticsearch创build了一个特殊的节点types:“客户端节点”,其中包含“无数据”,不能成为“主节点”。 客户端节点的function是在查询结束时执行最后的资源重合并sorting。
对于AWS,您可能会使用c3或c4实例types作为“客户端节点”
最佳做法是将负载平衡器指向客户机节点的查询。
干杯!
参考文献:
- Elasticsearch节点types
- Elasticsearch:碎片路由algorithm
- Elasticsearch:副本碎片
- Elasticsearch:集群状态,即碎片路由表
- ElasticHQ – Elasticsearchvideo介绍
- Elasticsearch:碎片数量和集群缩放
你想要devise“故障转移”是正确的,在AWS中,我build议你这样做。
1)限制集群中可以select主节点的节点。 其余的,设置node.client:true。 根据您select多less主可选节点来决定可用于故障切换的可用数量。
2)创build一个只包含主可选节点的ELB。
3)在Route 53中,为您的集群创build一个CNAME,并将其值设置为ELB的DNS名称。