我有一个基于 otp 原则构建的标准 Erlang 应用程序。我计划按照以下说明将我的 Erlang 节点投入生产:
- 接收公共 IP 上的所有流量(haproxy)
- haproxy 将它们连接到一个可用的后端 erlang 节点
所有这些都运行得很好,然而在基于会话的 http 事务的情况下,很可能其中一个 Erlang 节点接收请求,而该节点的会话相关进程驻留在另一个 Erlang 节点上。
我的问题与处理此类案件的最佳策略有关:
- 第一个选项是将 haproxy 配置为基于源(即 ip 地址)进行平衡,这将始终保证来自单个 ip 的会话的所有请求都转到同一个后端 erlang 节点
- 第二个选项是将 haproxy 配置为基于某些与会话相关的 cookie 参数进行平衡(这基本上与情况 1 相同)
- 最后,由于我的 erlang 节点可以很好地相互通信,因此也可以简单地将 haproxy 配置为以循环方式进行平衡,并且当 erlang 节点接收到请求时,其会话进程驻留在另一个 erlang 节点上,它可以使用 rpc:call() 与 erlang 节点进行内部通信并提供请求。
1)、2) 的使用和设置相当简单,但是我读到并测试过基于 source/cookie/url_param 的平衡并不能确保后端之间的平等平衡。
3) 可以使用 Erlang 中的 mnesia 复制功能来实现。对于 3),我可能会遇到一个 Erlang 节点在最终响应请求之前与另一个 Erlang 节点进行内部通信的情况。
我想知道哪种方法更好以及为什么?考虑到我的 otp 应用程序处理大量实时数据(xmpp 协议),从长远来看,3) 会是更好的选择吗?
答案1
我认为这在很大程度上取决于你的一个节点在会话方面能够处理多少负载。至少在 HTTP 方面,IP 和 cookie 哈希在保持大量负载平衡方面做得相当不错短暂的会议。
例如,单个 IP 后面可能有许多客户(基于 cookie 的哈希应该有助于解决此问题)。如果单个节点只能处理相对较少的同时会话,则节点可能会超载。此外,如果会话持续时间较长,哈希的不平衡可能会很明显。另一方面,如果会话数量很大且持续时间很短,那么一个节点拥有更多连接的相对重要性可能并不那么重要。
理论上,我还希望通过某种形式的源或基于 cookie 的平衡,您将获得更好的缓存命中率。另一件需要考虑的事情是,如果您有 3 个节点,那么如果一个节点发生故障,即使负载平衡完美,其他每个节点的负载也会增加约 16%。所以你也应该考虑配置。
如果您可以在单个节点上处理大量请求,那么对我来说,第三个选项听起来像是在解决一个您没有的问题,而且当有一个更简单的选项可行时,您不太可能遇到这个问题。