nginx 负载均衡之 ngx_http_upstream_hash_module

本文介绍了如何利用NGINX的upstream模块和ngx_http_upstream_hash_module模块对非会话共享的集群进行负载均衡。通过配置hash方法,确保同一用户的请求始终分配到同一台服务器,即使部分服务器故障也能通过hash_again机制进行重新分配。

nginx的upstream模块可以定义后端负载集群,负载的分配方式也有好几种,比如 ip_hash,RR,weight,url_hash,fair等。如果后端集群session不共享的 话,ip_hash,RR,weight,fair等负载均衡方式都将不适用,唯一可用的就是url_hash了。

要用url_hash需要安装第三方模块ngx_http_upstream_hash_module 。安装以及配置方法点击超链接即可。我这里主要介绍如何利用ngx_http_upstream_hash_module对session不共享的集群如何做负载均衡。

upstream的配置如下:

upstream pool1 {
hash   $cookie_jsessionid;
server server1:80;
server server2:80;
server server3:80;
hash_again 1;
}

为了保障同一个用户始终分配到同一个后端服务器,我们需要找到能唯一标示用户的标志,毫无疑问,非sessionid莫属了哈哈。因为服务器端也是 根据sessionid区分唯一用户的。所以我们hash用的变量是$cookie_jsessionid 。那么hash_again是什么意思呢?顾名思义hash_again就是再做一次hash的意思,那么什么情况下再做一次hash呢?为什么要再做一 次hash呢?我们配上access_log来看看nginx都做了些什么。

access_log格式配置如下:

log_format  main  ‘$remote_addr – $remote_user [$time_local] “$request” ‘
‘$status $body_bytes_sent ‘
‘”$http_user_agent” “$http_x_forwarded_for”‘
‘”$upstream_addr” “$upstream_cache_status” “$upstream_status” “$upstream_response_time” “$cookie_jsessionid“‘;

我们主要看upstream_addr、upsteam_status和cookie_jsessionid

首先我们访问下index.jsp,日志如下:

123.127.98.133 – - [02/Jul/2011:19:31:42 +0800] “GET /reg/register.jsp HTTP/1.1″ 200 14540 “Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1″ “-”"server1:80” “-” “200” “0.017″ “-

此时访问的是server1 sessionid居然为空!其实也可以理解第一次访问时确实木有sessionid,因为sessionid是服务器端生成后写到浏览器的cookie 里的,所以第一次访问肯定没有sessionid了。这样一来,我们可以推测所有用户的第一次请求都是发给同一台后端服务器的。这样的话如果恰好宕机的是 负责处理第一次用户的请求的服务器的话,那么所有的新访问的用户都将无法访问。

F5刷新页面:

123.127.98.133 – - [02/Jul/2011:19:31:46 +0800] “GET http://abc.efg.com/index.jsp” 200 8920 “Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1″ “-”"server2:80” “-” “200” “0.002″ “abcC8pjNRr3jGbAWKNQdt

有sessionid了,而且请求被重新分配到了server2了,而且之后用户所有的操作都分配到了server2。这个时候我们停掉server2,再次F5刷新页面。日志出如下:

123.127.98.133 – - [02/Jul/2011:19:33:08 +0800] “GET http://abc.efg.com/index.jsp” 200 14540 ” “Mozilla/5.0 (Windows NT 5.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1″ “-”"server2:80, server1:80” “-” “502, 200” “0.002, 0.015″ “abcC8pjNRr3jGbAWKNQdt

此时虽然我们已经停掉了server2但是我们仍然可以打开页面,为嘛?!此时hash_again大发神威了,此时我们可以从日志里看到 server2返回502,server1返回200。也就是说nginx请求server2是发现,靠!server2挂了,于是基于原来得到的 hash值再次进行hash,从而将请求发往了另外一台机器server1。之后所有的请求也都是这样,先请求server2,server2不可用,重 新hash,访问server1。那么hash_again=2时代表什么了?如果按照我们的配置hash_again=1,那么当server2和 server1都蛋掉,但是server3可用。用户请求时仍然会无法访问。如果我们改成hash_again=2,那么nginx会进行两次hash尝 试,尝试访问后端其他可以用的机器。也就是说hash_again的值越大,整个系统的可用性就越高。


<think>好的,用户提到“ngx_http_upstream_least_conn_module.c没有这个文件”,我需要先理解他们为什么会遇到这个问题。首先,用户可能在尝试应用某个补丁或者编译Nginx时遇到了错误,提示找不到这个文件。接下来,我需要回忆Nginx的源码结构,确认是否存在这个文件。 根据我的知识,Nginx负载均衡模块如least_conn(最小连接数算法)通常在`src/http/modules/`目录下,但具体的文件名可能有所不同。例如,round_robin模块对应的文件是`ngx_http_upstream_round_robin.c`,而least_conn模块可能没有单独的.c文件,或者名字不同。可能用户混淆了模块名称和实际文件名,或者他们使用的Nginx版本中该模块的实现方式不同。 接下来,我需要考虑用户为什么会寻找这个文件。可能他们在尝试修改least_conn模块的代码,或者应用一个针对该模块的补丁,但补丁指向的文件不存在。这时候,用户可能遇到了拼写错误,或者补丁适用于旧版本Nginx,而新版本中文件结构发生了变化。 另外,用户可能误解了模块的组织方式。有些Nginx模块可能将多个功能集成在一个文件中,或者least_conn模块的实现分散在其他文件中。例如,可能在`ngx_http_upstream_round_robin.c`中包含了部分逻辑,或者least_conn模块的代码在另一个文件中,如`ngx_http_upstream_least_conn_module.c`确实不存在,而是以其他方式实现。 需要验证不同Nginx版本的文件结构。例如,在较新的版本中,可能模块的组织有所调整。如果用户下载的源码版本中没有这个文件,那么他们可能需要检查是否下载了正确的版本,或者模块是否被编译为动态模块而非静态包含。 此外,用户可能在查找文档或示例代码时遇到了错误,导致他们误以为存在这个文件。需要引导他们检查官方文档或源码仓库,确认文件的存在与否。 最后,总结可能的原因:文件名拼写错误、Nginx版本差异、模块实现方式不同、文件位置变更。需要指导用户如何正确查找相关模块的代码,或调整他们的补丁路径。</think>--- ### **问题解析** 当提示 `ngx_http_upstream_least_conn_module.c 没有这个文件` 时,通常有以下原因: 1. **模块名称混淆** Nginx 的 `least_conn`(最小连接数)负载均衡模块的源码文件实际名为 **`ngx_http_upstream_least_conn_module.c`**,但不同版本中可能: - 文件路径不同(如 `src/http/modules/`) - 模块代码集成在其他文件中(例如动态模块与静态模块的差异) 2. **版本差异** - **旧版 Nginx**(如 1.18 之前):`least_conn` 模块代码可能直接嵌入在核心文件(如 `ngx_http_upstream.c`)。 - **新版 Nginx**(如 1.19+):该模块可能被拆分为独立文件或编译为动态模块(`.so`)。 3. **编译配置问题** 若未在编译时通过 `--with-http_upstream_least_conn_module` 启用该模块,源码文件可能未被包含。 --- ### **解决方案** #### **1. 确认文件是否存在** 通过以下命令搜索源码目录: ```bash # 进入 Nginx 源码根目录 find . -name "*least_conn*" ``` - **若存在**:检查文件路径是否与补丁或配置中的引用路径一致。 - **若不存在**:说明你的 Nginx 版本未以静态方式包含该模块源码。 --- #### **2. 检查模块编译方式** - **静态模块**: 需在编译时通过 `--with-http_upstream_least_conn_module` 显式启用。 ```bash ./configure --with-http_upstream_least_conn_module make && make install ``` - **动态模块**: 某些版本会将 `least_conn` 编译为动态模块(`.so` 文件),需在配置文件中加载: ```nginx load_module modules/ngx_http_upstream_least_conn_module.so; ``` --- #### **3. 版本适配操作** - **旧版迁移到新版**: 若从旧版升级,需注意模块代码可能被重构。例如: - 旧版逻辑可能位于 `ngx_http_upstream_round_robin.c` 中。 - 新版可能将 `least_conn` 分离到独立文件。 - **源码补丁问题**: 如果尝试应用第三方补丁但提示文件缺失,需检查补丁是否适配当前版本。例如: ```bash # 错误示例:补丁路径指向不存在的文件 patch -p1 < some.patch # 报错 "ngx_http_upstream_least_conn_module.c not found" ``` **修正方法**: 修改补丁文件中的路径,使其匹配实际源码结构。 --- ### **常见场景与修复示例** | 场景 | 解决方案 | |------|----------| | 补丁文件路径错误 | 用文本编辑器打开补丁文件,将 `ngx_http_upstream_least_conn_module.c` 改为实际路径(如 `src/http/modules/ngx_http_upstream_least_conn_module.c`) | | 动态模块未加载 | 在 `nginx.conf` 顶部添加 `load_module` 指令 | | 编译未启用模块 | 重新运行 `./configure` 并添加 `--with-http_upstream_least_conn_module` | --- ### **扩展知识:Nginx 负载均衡模块结构** Nginx 核心负载均衡模块的文件命名规则一般为: ``` ngx_http_upstream_<算法名>_module.c ``` 例如: - 轮询算法:`ngx_http_upstream_round_robin_module.c` - 哈希算法:`ngx_http_upstream_hash_module.c` - IP 哈希算法:`ngx_http_upstream_ip_hash_module.c` 若某个模块文件缺失,可能是代码尚未拆分或需特定编译选项激活。 --- ### **总结** `ngx_http_upstream_least_conn_module.c` 缺失问题通常由 **版本差异** 或 **编译配置错误** 导致。建议: 1. 通过 `find` 命令确认文件是否存在 2. 检查编译参数是否启用该模块 3. 若需应用补丁,手动调整路径或联系补丁提供者适配新版源码
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值