Nginx的ip_hash指令

ip_hash
语法:ip_hash
默认值:none
使用环境:upstream
当对后端的多台动态应用服务器做负载均衡时,ip_hash指令能够将某个客户端IP的请求通过哈希算法定位到同一台后端服务器上。这样,当来自某个IP的用户在后端Web服务器A上登录后,再访问该站点的其他URL,能够保证其访问的还是后端Web服务器A。如果不采用ip_hash指令,假设来自某个IP的用户在后端Web服务器A上登录后,再访问该站点的其他URL,有可能被定向到后端Web服务器B,C...上,由于用户登录后SESSION信息是记录在服务器A上的,B,C...上没有,这时就会提示用户来登录。
使用ip_hash指令无法保证后端服务器的负载均衡,可能有些后端服务器接收的请求多,有些后端服务器收到的请求少,而且设置后端服务权重等方法将不起作用。所以,如果后端的动态应用服务器能够做到SESSION共享,还是建议采用后端服务的SESSION共享方式代替Nginx的ip_hash方式。
如果后端服务器有时要从Nginx负载均衡中摘除一段时间,你必须其标记为“down”,而不是直接从配置文件中删除或注释掉该后端服务器的信息。代码示例如6-6:
这样,当原来为4台后端服务时,摘除backend3.example后,Nginx仍然会按4台服务器进行哈希。如果直接注释掉“server backend3.example.com”这行,Nginx就会按照3台服务器进行重新

哈希,原来被哈希到backend1.example.com的客户端IP有可能被哈希backend2.example.com服务器上,原有的SESSION就会失效。



网络结构描述:
1个Nginx(前端)+2个tomcat(后端)

环境:
公司内网(网段:192.168.1.0/24),服务器也是分配的内网ip:192.168.1.4(暂定);后端两个tomcat:192.168.1.31/189
网站有session,所有Nginx启用ip_hash.

现象:
测试组用loadrunner模拟N多内网ip进行压测系统。发现,这些ip统一都转发到一个后端。


后经排查发现问题所在(结论最下面)。

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算法(该段代码为转发。原文链接: http://www.linuxidc.com/Linux/2014-02/96869.htm ):

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( ;; ) {
for(i = 0; i < 3; i++) {
hash = (hash * 113+ iphp->addr[i]) % 6271; 
 
1、for循环 i 取 012三个值,而ip的点分十进制表示方法将ip分成四段(如:192.168.1.1),但是这里循环时只将ip的前三个端作为参数加入hash函数。这样做的目的是保证ip地址前三位相同的用户经过hash计算将分配到相同的后端server。
作者的这个考虑是极为可取的,因此ip地址前三位相同通常意味着来着同一个局域网或者相邻区域,使用相同的后端服务让nginx在一定程度上更具有一致性。
 
通过上述解释,已经基本判断出问题所在了。。
主要原因就是,公司局域网用的192.168.1.0/24 C类地址,这样Nginx在ip_hash(for循环后三个参数统一计入hash值)的时候,就将该类所有ip都转发到一个后端了。
 
另,晕了我半天了。。。不论A类B类C类等网络地址,Nginx的ip_hash算法都将一个ip地址的前三段作为hash的关键字。。(规定)


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
`ip_hash`是Nginx的一种负载均衡算法,它基于客户端的IP地址来确定将请求转发给哪个后端服务器。使用`ip_hash`算法,相同IP地址的客户端将始终被分配到同一个后端服务器,这有助于保持会话的一致性。 要配置Nginx使用`ip_hash`算法进行负载均衡,可以按照以下步骤进行: 1. 打开Nginx的配置文件。通常在Linux系统中,配置文件位于`/etc/nginx/nginx.conf`或`/etc/nginx/conf.d/default.conf`。 2. 在`http`块内添加一个`upstream`块,定义要进行负载均衡的服务器列表。示例代码如下: ```nginx http { upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com; } ... } ``` 在上面的示例中,我们使用`ip_hash`指令在`upstream`块中启用了IP哈希负载均衡算法,并列出了要进行负载均衡的服务器。 3. 在Nginx的配置文件中,找到你要使用负载均衡的位置(如`location`块),并将其代理到上面定义的`backend`服务器组。示例代码如下: ```nginx http { upstream backend { ip_hash; server backend1.example.com; server backend2.example.com; server backend3.example.com; } server { ... location / { proxy_pass http://backend; } ... } } ``` 在上面的示例中,我们使用`proxy_pass`将请求代理到名为`backend`的服务器组。 4. 保存配置文件并重新加载Nginx配置。在终端中执行以下命令: ```shell sudo nginx -t # 检查配置文件语法是否正确 sudo systemctl reload nginx # 重新加载Nginx配置 ``` 这样配置后,Nginx将使用`ip_hash`算法将请求分发给后端服务器。相同IP地址的客户端将被分配到同一个后端服务器上,从而保持会话的一致性。 请注意,`ip_hash`算法适用于基于客户端IP地址的负载均衡,并且要求Nginx编译时启用了`--with-http_upstream_ip_hash_module`模块。确保你的Nginx版本支持此功能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值