ip-hash的算法
for (;;) { for (i = 0; i < 3; i++) { hash = (hash * 113 + iphp->addr[i]) % 6271; //iphp->addr[i]为ip的点分十进制法的第i段 } p = hash % iphp->rrp.peers->number; n = p / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t)); if (!(iphp->rrp.tried[n] & m)) { ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get ip hash peer, hash: %ui %04XA", p, m); peer = &iphp->rrp.peers->peer[p]; /* ngx_lock_mutex(iphp->rrp.peers->mutex); */ if (!peer->down) { if (peer->max_fails == 0 || peer->fails < peer->max_fails) { break; } if (now - peer->accessed > peer->fail_timeout) { peer->fails = 0; break; } } iphp->rrp.tried[n] |= m; /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */ pc->tries--; } if (++iphp->tries >= 20) { return iphp->get_rr_peer(pc, &iphp->rrp); } }
for循环i取 012三个值,而ip的点分十进制表示方法将ip分成四段(如:192.168.1.1),但是这里循环时只是将ip的前三个段作为参数加入hash函数。这样做的目的是保证ip地址前三位相同的用户经过hash计算将分配到相同的后端server。
由于Ng前面是一个硬负载,和Ng交换的IP是硬负载地址池中的多个固定的IP。从而导致Ng把请求都转发到一个机器上面啦。
解决方案:
第一种:
修改ip_hash代码算法中的取值,解决问题,可以参考
https://blog.csdn.net/qq_45367825/article/details/111355402?utm_medium=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-2.control&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2~default~BlogCommendFromMachineLearnPai2~default-2.control
第二种:
通过HTTP_X_FORWARDED_FOR获取IP地址
server { listen 80; ..... location /{ set_real_ip_from 10.48.10.0/24;#需要过滤掉的IP set_real_ip_from 61.22.22.22; real_ip_header X-Forwarded-For; real_ip_recursive on; } }