nginx通过ip-hash算法负载不均或不起效问题

本文深入解析了Nginx中ip_hash负载均衡策略的工作原理,特别是其对于客户端IP地址的处理方式。指出该算法仅采用IP地址的前三段进行哈希计算,这可能导致来自同一局域网内的所有请求都被定向到同一台后端服务器。

现象:Nginx和客户端处于同一个局域网,使用ip_hash负载均衡策略,不同客户端的请求全部都分发到同一个后台服务器

 

原因:

1、请看官方解释:
This directive causes requests to be distributed between upstreams based on the IP-address of the client. 
The key for the hash is the class-C network address or the entire IPv6-address of the client. IPv6 is supported for ip_hash since 1.3.2 or 1.2.2. This method guarantees that the client request will always be transferred to the same server. But if this server is considered inoperative, then the request of this client will be transferred to another server. This gives a high probability clients will always connect to the same server. (简译:将客户端ip转化成C类网络地址,然后将该网络地址当作hash关键字,来保证这个客户端请求总是被转发到一台服务器上)

 

2、请看Nginx的ip hash算法

 


 
  1. for ( ;; ) {

  2.  

  3.          for (i = 0; i < 3; i++) {  

  4.             hash = (hash * 113 + iphp->addr[i]) % 6271; //iphp->addr[i]为ip的点分十进制法的第i段

  5.         }

  6.  

  7.         p = hash % iphp->rrp.peers->number;

  8.  

  9.         n = p / (8 * sizeof(uintptr_t));

  10.         m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));

  11.  

  12.         if (!(iphp->rrp.tried[n] & m)) {

  13.  

  14.             ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,

  15.                             "get ip hash peer, hash: %ui %04XA", p, m);

  16.  

  17.             peer = &iphp->rrp.peers->peer[p];

  18.  

  19.             /* ngx_lock_mutex(iphp->rrp.peers->mutex); */

  20.  

  21.             if (!peer->down) {

  22.  

  23.                 if (peer->max_fails == 0 || peer->fails < peer->max_fails) {

  24.                     break;

  25.                 }

  26.  

  27.                 if (now - peer->accessed > peer->fail_timeout) {

  28.                     peer->fails = 0;

  29.                     break;

  30.                 }

  31.             }

  32.  

  33.             iphp->rrp.tried[n] |= m;

  34.  

  35.             /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */

  36.  

  37.             pc->tries--;

  38.         }

  39.  

  40.         if (++iphp->tries >= 20) {

  41.             return iphp->get_rr_peer(pc, &iphp->rrp);

  42.         }

  43.     }

 

主要代码

 


 
  1. for(i = 0; i < 3; i++) {

  2. hash = (hash * 113+ iphp->addr[i]) % 6271;

  3. }

 

for循环i取 012三个值,而ip的点分十进制表示方法将ip分成四段(如:192.168.1.1),但是这里循环时只是将ip的前三个段作为参数加入hash函数。这样做的目的是保证ip地址前三位相同的用户经过hash计算将分配到相同的后端server。

作者的这个考虑是极为可取的,因此ip地址前三位相同通常意味着来着同一个局域网或者相邻区域,使用相同的后端服务让nginx在一定程度上更具有一致性。

通过上述解释,已经基本判断出问题所在了。。
主要原因就是,公司使用的局域网前三段ip相同,这样Nginx在ip_hash(for循环后三个参数统一计入hash值)的时候,就将该类所有ip都转发到一个后端了。
 
另,不论A类B类C类等网络地址,Nginx的ip_hash算法都将一个ip地址的前三段作为hash的关键字。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值