是否不需要使用带有 ElasticSearch 的负载均衡器?

Posted

技术标签:

【中文标题】是否不需要使用带有 ElasticSearch 的负载均衡器?【英文标题】:Is using a load balancer with ElasticSearch unnecessary? 【发布时间】:2014-09-05 05:23:55 【问题描述】:

我有一个在 AWS EC2 上运行的由 3 个 ElasticSearch 节点组成的集群。这些节点是使用 OpsWorks/Chef 设置的。我的意图是将这个集群设计得非常有弹性和弹性(节点可以在需要时进出)。

从我读到的所有关于 ElasticSearch 的文章来看,似乎没有人建议在集群前面放置一个负载均衡器。相反,似乎建议是做以下两件事之一:

    将你的客户端指向一个节点的URL/IP,让ES为你做负载均衡,希望这个节点永远不会宕机。

    将所有节点的 URL/IP 硬编码到客户端应用程序中,并让应用程序处理故障转移逻辑。

我的背景主要是在网络农场中,创建一个巨大的自治网络服务器池只是常识,在它们前面扔一个 ELB,让负载平衡器决定哪些节点是活动的还是死的。为什么 ES 似乎不支持同样的架构?

【问题讨论】:

【参考方案1】:

您不需要负载平衡器 - ES 已经提供了该功能。您只需要另一个组件,它可能会出现异常行为并且会添加不必要的网络跃点。

ES 会将您的数据分片(默认为 5 个分片),它会尝试在您的实例之间平均分配。在您的情况下,2 个实例应该有 2 个分片,而 1 个只有一个,但您可能希望将分片更改为 6 个以实现均等分布。

默认情况下,复制设置为"number_of_replicas":1,因此每个分片都有一个副本。假设您使用 6 个分片,它可能看起来像这样(R 是一个复制分片):

节点0:1、4、R3、R6 节点1:2、6、R1、R5 节点2:3、5、R2、R4

假设 node1 死亡,集群将更改为以下设置:

node0:1、4、6、R3 + 新副本 R5、R2 node2:3、5、2、R4 + 新副本 R1、R6

根据您的连接设置,您可以连接到一个实例(传输客户端),也可以加入集群(节点客户端)。使用节点客户端,您将避免双跳,因为您将始终连接到正确的分片/索引。使用传输客户端,您的请求将被路由到正确的实例。

因此,您无需为自己进行负载平衡,您只会增加开销。自动聚类可能是 ES 最大的优势。

【讨论】:

感谢您的回答。我想我更关心故障转移平衡。我知道 ES 会为我做负载均衡,但是如果我连接的节点出现故障或停止服务怎么办?在 ELB 的情况下(至少就 Web 服务器而言),它将平衡所有服务节点之间的请求。 ES 集群有类似的模式吗? @xeraa 所以“节点”客户端通过广播或其他方式自动解析可用的 elasticsearhc 节点/集群? 您可以提供具有正确端口的 IP/DNS 名称数组(或您的编程语言中所称的任何名称)。其中至少一个必须是可达的,其余的应该由 ES 处理 这种方法的牺牲是现在您的客户端直接依赖于服务器拓扑。而且,不,您不是“添加另一个网络跃点”。您只是在更改域名解析的方式。除非您甚至在谈论在客户端配置中使用 IP 地址,在这种情况下......是的。 这不能回答问题。这是一篇关于 ES 如何在内部平衡数据的好文章,但是连接到 ES 集群的客户端应用程序仍然需要一种机制来在 node1 失败时切换到 node2 的 IP。浮动 IP 或 IP 负载均衡器可以完成这项工作,但它不包含在 ES 中。【参考方案2】:

您想要设计“故障转移”是完全正确的,在 AWS 中,我建议您这样做。

1) 限制集群中可以被选为主节点的节点。其余的,设置 node.client: true。根据您希望有多少可供故障转移使用,您可以选择有多少主可选节点。

2) 创建一个只包含可选主节点的 ELB。

3) 在 Route 53 中,为您的集群创建一个 CNAME,并将值设置为 ELB 的 DNS 名称。

【讨论】:

【参考方案3】:

我认为对 Elasticsearch 集群进行负载平衡是个好主意(设计一个容错系统,对单节点故障具有弹性。)

要构建您的集群,您需要了解 Elasticsearch 的两个主要功能:1. 编写和更新文档以及 2. 查询文档。

在 elasticsearch 中编写/索引文档:

    当一个新文档进入 Elasticsearch 进行索引时,Elasticsearch 会使用“分片路由算法”确定该文档应分配到的“主分片” 与分片关联的 Lucene 进程“映射”文档中的字段; Lucene 进程将文档添加到分片的 Lucene“倒排索引”中 然后任何“副本分片”都会收到该文档;副本分片“映射”文档并将文档添加到副本分片的 Lucene“倒排索引”

在 Elasticsearch 中查询文档:

    默认情况下,当查询发送到 Elasticsearch 时,查询会命中一个节点——这将成为该查询的“查询节点”或“网关查询节点” 节点将查询广播到索引中的每个分片(主分片和副本分片) 每个分片对分片的本地 Lucene 倒排索引执行查询。 每个分片返回前10-20个结果给“网关查询节点” “网关查询节点”然后对从其他分片返回的组合结果执行合并排序, 一旦合并排序完成,“网关查询节点”并将结果返回给客户端 合并排序占用大量 CPU 和内存资源

为写入/索引/更新构建负载均衡器

Elasticsearch 自行管理分片在节点上的位置。 “主节点”保存并更新“分片路由表”。 “主节点”将分片路由表的副本提供给集群中的其他节点。

通常,您不希望您的主节点做更多的工作,而不仅仅是对集群进行健康检查、更新路由表和管理分片。

最好将负载均衡器指向“数据节点”(数据节点是包含数据=分片的节点)并让数据节点使用其分片路由表将写入写入正确的分片。

查询架构

Elasticsearch 创建了一个特殊的节点类型:“客户端节点”,它包含“无数据”,不能成为“主节点”。客户端节点的功能是在查询结束时执行最终的资源重合并排序。

对于 AWS,您可能会使用 c3 或 c4 实例类型作为“客户端节点”

最佳做法是将查询的负载均衡器指向客户端节点。

干杯!

参考资料:

    Elasticsearch Node Types Elasticsearch: Shard Routing Algorithm Elasticsearch: Replica Shards Elasticsearch: Cluster State i.e. the Shard Routing Table ElasticHQ - Introduction to Elasticsearch Video Elasticsearch: Shard numbers and Cluster Scaling

【讨论】:

感谢您的详细记录!【参考方案4】:

主节点出现故障时该怎么办,有点不清楚。挖掘后,这里有几个选项:

    如果您使用客户端连接到 elasticsearch 集群,您可以在连接配置中指定一组 DNS 名称。客户端将尝试按顺序解析 DNS。如果第一个失败,将尝试第二个。 使用循环 DNS。类似于第一个选项,但没有客户端。 这两个选项都可能导致延迟,因为 DNS 需要首先失败才能路由到下一个可用别名。 DNS 或客户端无法知道特定主机已关闭。 使用某种负载平衡器,这样 LB 会提前知道行为不端的主机,而不会造成任何延迟。

【讨论】:

你必须使用单节点主配置。

以上是关于是否不需要使用带有 ElasticSearch 的负载均衡器?的主要内容,如果未能解决你的问题,请参考以下文章

是否可以为一个带有使用 debezium 和 kafka 的表的数据库创建一个 Elasticsearch 索引?

Elasticsearch:使用 Elasticsearch Java client 8.0 来连接带有 HTTPS 的集群

Logstash在未来编写Elasticsearch索引

ElasticSearch 基本操作

Elasticsearch:从零开始创建一个 REST handler 插件

带有 ElasticSearch 的嵌套树的构面