概念

根据用户请求的ip,利用算法映射成hash值,分配到特定的tomcat服务器中。主要是为了实现负载均衡,只要用户ip固定,则hash值固定,特定用户只能访问特定服务器,解决了session的问题。

源码分析

ip_hash算法的处理代码位于src\http\modules\ngx_http_upstream_ip_hash_module.c。主要的处理代码如下:

// 最大失败次数、超时时间、最大连接数等相关配置
#define NGX_HTTP_UPSTREAM_CREATE        0x0001
#define NGX_HTTP_UPSTREAM_WEIGHT        0x0002
#define NGX_HTTP_UPSTREAM_MAX_FAILS     0x0004
#define NGX_HTTP_UPSTREAM_FAIL_TIMEOUT  0x0008
#define NGX_HTTP_UPSTREAM_DOWN          0x0010
#define NGX_HTTP_UPSTREAM_BACKUP        0x0020
#define NGX_HTTP_UPSTREAM_MAX_CONNS     0x0100static ngx_int_t
ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data)
{ngx_http_upstream_ip_hash_peer_data_t  *iphp = data;time_t                        now;ngx_int_t                     w;uintptr_t                     m;ngx_uint_t                    i, n, p, hash;ngx_http_upstream_rr_peer_t  *peer;ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,"get ip hash peer, try: %ui", pc->tries);/* TODO: cached */ngx_http_upstream_rr_peers_rlock(iphp->rrp.peers);if (iphp->tries > 20 || iphp->rrp.peers->single) {ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers);return iphp->get_rr_peer(pc, &iphp->rrp);}now = ngx_time();pc->cached = 0;pc->connection = NULL;// 原始哈希值hash = iphp->hash;for ( ;; ) {// 计算ip hashfor (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) {hash = (hash * 113 + iphp->addr[i]) % 6271;}// 根据hash和权重找到对应服务器w = hash % iphp->rrp.peers->total_weight;peer = iphp->rrp.peers->peer;p = 0;while (w >= peer->weight) {w -= peer->weight;peer = peer->next;p++;}n = p / (8 * sizeof(uintptr_t));m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));if (iphp->rrp.tried[n] & m) {goto next;}ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0,"get ip hash peer, hash: %ui %04XL", p, (uint64_t) m);ngx_http_upstream_rr_peer_lock(iphp->rrp.peers, peer);// 如果服务器不可用,不做后续处理if (peer->down) {ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer);goto next;}// 如果超过最大失败次数或者超时,不做后续处理if (peer->max_fails&& peer->fails >= peer->max_fails&& now - peer->checked <= peer->fail_timeout){ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer);goto next;}// 如果超过最大连接数,不做后续处理if (peer->max_conns && peer->conns >= peer->max_conns) {ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer);goto next;}break;next:if (++iphp->tries > 20) {ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers);return iphp->get_rr_peer(pc, &iphp->rrp);}}iphp->rrp.current = peer;pc->sockaddr = peer->sockaddr;pc->socklen = peer->socklen;pc->name = &peer->name;// 连接数自增peer->conns++;if (now - peer->checked > peer->fail_timeout) {peer->checked = now;}ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer);ngx_http_upstream_rr_peers_unlock(iphp->rrp.peers);iphp->rrp.tried[n] |= m;iphp->hash = hash;return NGX_OK;
}

算法的核心处理代码如下:

for (i = 0; i < (ngx_uint_t) iphp->addrlen; i++) {hash = (hash * 113 + iphp->addr[i]) % 6271;
}

通过查看源码得知,ipv4的情况下iphp->addrlen的值固定为3,源代码如下:

switch (r->connection->sockaddr->sa_family) {case AF_INET:   // ipv4sin = (struct sockaddr_in *) r->connection->sockaddr;iphp->addr = (u_char *) &sin->sin_addr.s_addr;iphp->addrlen = 3;  break;#if (NGX_HAVE_INET6)case AF_INET6:  // ipv6sin6 = (struct sockaddr_in6 *) r->connection->sockaddr;iphp->addr = (u_char *) &sin6->sin6_addr.s6_addr;iphp->addrlen = 16; break;
#endifdefault:iphp->addr = ngx_http_upstream_ip_hash_pseudo_addr;iphp->addrlen = 3;}

假如我们传递的ip为192.168.41.33,hash值得计算流程可以拆分为:

hash0 = iphp->hash;# iphp->addr[0]--->192
hash1 = (hash0 * 113 + iphp->addr[0]) % 6271;# iphp->addr[1]--->168
hash2 = (hash1 * 113 + iphp->addr[1]) % 6271;# iphp->addr[2]--->41
hash3 = (hash2 * 113 + iphp->addr[2]) % 6271;

经分析得知,ip_hash实际是取ip地址得前三个字段计算得来,那么譬如192.168.41.xxx同一网段的ip访问的是同一个tomacat。

根据hash和权重找到对应的后端,源代码如下:

w = hash % iphp->rrp.peers->total_weight;
peer = iphp->rrp.peers->peer;
p = 0;while (w >= peer->weight) {w -= peer->weight;peer = peer->next;p++;
}// ...

需要注意的一点是,当一个正在以ip_hash方式管理的服务器在实际操作环境中被移除时,在nginx.conf中不能直接把对应的配置删除,在后面加down即可,因为删除后需要重新计算hash,处理这一过程会更加消耗资源。nginx.conf配置文件修改如下:

# 以ip_hash的方式实现负载均衡, 添加ip_hash即可
upstream dongserver {ip_hash;      server 192.168.41.33:8080;server 192.168.41.34:8081;server 192.168.41.35:8082 down;  # 服务器不可用
}

nginx源码中对此的处理如下:

# upstream块结构体
struct ngx_http_upstream_rr_peer_s {//...ngx_uint_t                      down;    // 服务器是否可用//...
};# 当判断到down标志被竖起来之后,不做后续处理
if (peer->down) {ngx_http_upstream_rr_peer_unlock(iphp->rrp.peers, peer);goto next;
}

nginx的ip_hash算法相关推荐

  1. nginx加权轮训算法

    nginx加权轮训算法 nginx upstream负载均衡默认采用轮训方法 http {upstream tomcats{server 192.168.25.131:8080;server 192. ...

  2. nginx负载均衡算法

    配置方式 NGINX配置负载均衡主要是在nginx.conf文件中里upstream模块 1.upstream模块应放于nginx.conf配置的http{}标签内 2.upstream模块默认算法是 ...

  3. nginx 负载均衡算法

    1.轮询(RR,默认负载均衡算法) 按顺序选择组内服务器处理请求.若某个服务器在处理请求时出错,则请求会被顺次交给组内的下一个服务器,以此类推,直到返回正常的响应为止. 若组内所有的服务器都出错,则返 ...

  4. nginx 负载 sessionid 不一致_你不知道的Nginx负载均衡算法,快进来迅速掌握

    关于负载均衡的三种算法,轮询法,随机法,最小连接法,这三种负载均衡的算法,但是关于负载均衡还有其他的算法,我们也需要你去看,而且在面试的过程中,很有可能是会问到的呦. 对于要实现高性能集群,选择好负载 ...

  5. Nginx流量拦截算法

    0x00.About 电商平台营销时候,经常会碰到的大流量问题,除了做流量分流处理,可能还要做用户黑白名单.信誉分析,进而根据用户ip信誉权重做相应的流量拦截.限制流量. Nginx自身有的请求限制模 ...

  6. nginx+tocmat ip_hash做负载均衡时,一台tomcat宕机时没有转发问题

    upstream 127.0.0.1{ip_hash; # ip_hash策略server 127.0.0.1:8080;server 127.0.0.1:8081; } server{locatio ...

  7. nginx 配置ip_hash不会自动剔除宕机的服务器

    默认情况下不会自动剔除,但是有默认的max_fails参数和fail_timeout参数可以让nginx判断请求的服务器是否down,若down,则会再hash选择下一台服务器. ip_hash 指令 ...

  8. Nginx流量拦截算法 1

    0x00.About 电商平台营销时候,经常会碰到的大流量问题,除了做流量分流处理,可能还要做用户黑白名单.信誉分析,进而根据用户ip信誉权重做相应的流量拦截.限制流量. Nginx自身有的请求限制模 ...

  9. 2.9 Nginx一致性HASH算法

    hash算法带来的问题 问题: 当有服务宕机,或者新增某台服务器,会出现的问题: 请求可能会集中到某一台机器.导致某台服务请求量剧增,其他机器可能空闲. 造成原因: hash算法会重新进行计算,同时用 ...

最新文章

  1. [转]关于父亲的故事
  2. java获取excle表格对象_Java使用excel工具类导出对象功能示例
  3. IOS简单的登陆界面
  4. 节省50%部署时间的5大KS8服务
  5. 【自定义Android带图片和文字的ImageButton】
  6. 21. PE结构-PE各个结构的基本概念
  7. 三、 redis进阶篇
  8. 信息系统项目管理08——项目质量管理
  9. nfc卡模式与标准模式_马苏开启年后减肥模式,素颜自拍打卡,皮肤光滑香汗淋漓惹人注目...
  10. [安全防护]诺顿产品之Symantec Endpoint Protection
  11. 从一个月2500没人要到大厂技术主管的编程之路|我的十年
  12. 计算电磁学中的矩量法及其求解过程介绍
  13. z8350cpu linux,跑分 Intel Z8350小有提升_平板电脑评测-中关村在线
  14. 互联网舆情数据监测预警分析系统软件不收费的有哪些详解
  15. guided filter matlab,导向滤波(Guided Filter)的解析与实现
  16. 【优化】共轭函数(Conjugate Function)超简说明
  17. 小程序(四):微信登录功能的实现+云开发数据库
  18. html用手机什么软件能编写,目前编写一款简单的手机应用APP一般用什么编程语言?...
  19. 音频节奏检测(Onset Detection)
  20. python人脸识别算法_python人脸算法

热门文章

  1. Spring支持的几种bean的作用域
  2. 斐波那契数列 C语言 数组 非数组 函数
  3. Android _ MVVM 设计模式的一种实现方式,最新BAT大厂面试者整理的Android面试题目
  4. android设备uuid、udid
  5. 蓝桥杯--数学2 AcWing 1211. 蚂蚁感冒
  6. 大数据存储系统学习笔记(一)
  7. 【编译原理】flex实现词法分析器
  8. Feed-Forward Layers
  9. 今天用Qt整合腾讯会议sdk时,编译的程序报:无法启动此程序,因为计算机中丢失ucrtbased.dll。尝试重新安装改程序以解决
  10. 从存储、实时、安全的角度谈如何建立完整可用的企业大数据平台