nginx的ip_hash算法
概念
根据用户请求的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算法相关推荐
- nginx加权轮训算法
nginx加权轮训算法 nginx upstream负载均衡默认采用轮训方法 http {upstream tomcats{server 192.168.25.131:8080;server 192. ...
- nginx负载均衡算法
配置方式 NGINX配置负载均衡主要是在nginx.conf文件中里upstream模块 1.upstream模块应放于nginx.conf配置的http{}标签内 2.upstream模块默认算法是 ...
- nginx 负载均衡算法
1.轮询(RR,默认负载均衡算法) 按顺序选择组内服务器处理请求.若某个服务器在处理请求时出错,则请求会被顺次交给组内的下一个服务器,以此类推,直到返回正常的响应为止. 若组内所有的服务器都出错,则返 ...
- nginx 负载 sessionid 不一致_你不知道的Nginx负载均衡算法,快进来迅速掌握
关于负载均衡的三种算法,轮询法,随机法,最小连接法,这三种负载均衡的算法,但是关于负载均衡还有其他的算法,我们也需要你去看,而且在面试的过程中,很有可能是会问到的呦. 对于要实现高性能集群,选择好负载 ...
- Nginx流量拦截算法
0x00.About 电商平台营销时候,经常会碰到的大流量问题,除了做流量分流处理,可能还要做用户黑白名单.信誉分析,进而根据用户ip信誉权重做相应的流量拦截.限制流量. Nginx自身有的请求限制模 ...
- 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 ...
- nginx 配置ip_hash不会自动剔除宕机的服务器
默认情况下不会自动剔除,但是有默认的max_fails参数和fail_timeout参数可以让nginx判断请求的服务器是否down,若down,则会再hash选择下一台服务器. ip_hash 指令 ...
- Nginx流量拦截算法 1
0x00.About 电商平台营销时候,经常会碰到的大流量问题,除了做流量分流处理,可能还要做用户黑白名单.信誉分析,进而根据用户ip信誉权重做相应的流量拦截.限制流量. Nginx自身有的请求限制模 ...
- 2.9 Nginx一致性HASH算法
hash算法带来的问题 问题: 当有服务宕机,或者新增某台服务器,会出现的问题: 请求可能会集中到某一台机器.导致某台服务请求量剧增,其他机器可能空闲. 造成原因: hash算法会重新进行计算,同时用 ...
最新文章
- [转]关于父亲的故事
- java获取excle表格对象_Java使用excel工具类导出对象功能示例
- IOS简单的登陆界面
- 节省50%部署时间的5大KS8服务
- 【自定义Android带图片和文字的ImageButton】
- 21. PE结构-PE各个结构的基本概念
- 三、 redis进阶篇
- 信息系统项目管理08——项目质量管理
- nfc卡模式与标准模式_马苏开启年后减肥模式,素颜自拍打卡,皮肤光滑香汗淋漓惹人注目...
- [安全防护]诺顿产品之Symantec Endpoint Protection
- 从一个月2500没人要到大厂技术主管的编程之路|我的十年
- 计算电磁学中的矩量法及其求解过程介绍
- z8350cpu linux,跑分 Intel Z8350小有提升_平板电脑评测-中关村在线
- 互联网舆情数据监测预警分析系统软件不收费的有哪些详解
- guided filter matlab,导向滤波(Guided Filter)的解析与实现
- 【优化】共轭函数(Conjugate Function)超简说明
- 小程序(四):微信登录功能的实现+云开发数据库
- html用手机什么软件能编写,目前编写一款简单的手机应用APP一般用什么编程语言?...
- 音频节奏检测(Onset Detection)
- python人脸识别算法_python人脸算法
热门文章
- Spring支持的几种bean的作用域
- 斐波那契数列 C语言 数组 非数组 函数
- Android _ MVVM 设计模式的一种实现方式,最新BAT大厂面试者整理的Android面试题目
- android设备uuid、udid
- 蓝桥杯--数学2 AcWing 1211. 蚂蚁感冒
- 大数据存储系统学习笔记(一)
- 【编译原理】flex实现词法分析器
- Feed-Forward Layers
- 今天用Qt整合腾讯会议sdk时,编译的程序报:无法启动此程序,因为计算机中丢失ucrtbased.dll。尝试重新安装改程序以解决
- 从存储、实时、安全的角度谈如何建立完整可用的企业大数据平台