算法|Nginx的负载均衡没起作用?原来原因在这里

算法|Nginx的负载均衡没起作用?原来原因在这里


前些日子程序员小王因为一个奇怪的bug而又头秃了不少 。 原来是他们在客户内网系统里部署的项目出了问题 , 原本是配的两个后台节点 , 前面使用了Nginx做负载均衡 , 很常用的小型B/S系统部署方案 , 很简单明了 。 但是在客户那边出了问题 , 一台服务器承担了几乎所有流量 , 而另一台服务器基本上没有任何流量 。 这是什么原因呢?
小王反复看了Nginx的配置 , 没有问题 , 节点的upstream都配置了 , 也没有配置权重 , 也都单独试过网页能打开 。 但是就是每次都是一个节点门庭若市 , 另一个节点门可罗雀 。
小王试了好久 , 百思不得其解 , 无奈求助了资深程序员老李 。
老李不愧是资深程序员 , 很快就找出了问题所在 。 原来问题出在Nginx的负载均衡策略上面 。

小王配置的两个节点负载均衡 , 采用的是ip_hash策略 , 即基于客户端IP地址来确定访问哪个服务节点的策略 。 其算法很简单 , 根据请求所属客户端IP计算得到一个数值 , 然后把请求发往该数值对应的后端 。 所以同一个客户端的请求 , 都会发往同一个后台服务节点 。 除非该节点不可用了 。 Ip_hash策略的优点是能够保持会话 。
那么这个策略有什么问题呢?老李微笑的告诉小王 , 这个问题出在Nginx对Ip_hash的算法上 。 这段算法的核心部分如下:
for (i = 0; i < 3; i++) {
hash = (hash * 113 + iphp->addr[i
) % 6271; //iphp->addr[i
为ip的点分十进制法的第i段

通过客户端ip计算得到一个值 。 但是问题就出在这段算法上 , 我们可以看到 , 这段算法循环了三次 , 而正常的IP地址有四个部分 , 这里只是将IP的前三个部分作为参数加入hash函数 。 因此 , 如果前三部分是一样的话 , 那么意味着他们都会被分配到同一台服务器上 。
那么为什么Nginx要这样设计呢?因为IP地址前三位相同一般意味着来自同一个局域网或者相领区域 , 使用相同的后端服务能够让Nginx在一定程度上更具有一致性 。
所以因为客户的内网用户端多在同一个网段 , 所以最终的结果就是在同一个网段的请求都被Nginx分发到了一个节点上 , 导致了两个节点的流量不均衡 。
听了老李的话 , 小王恍然大悟 。 看来对技术永远不能一知半解 , 不知道在什么小地方就隐藏着潜在的问题 。
【算法|Nginx的负载均衡没起作用?原来原因在这里】