上游负载均衡与故障隔离
目标
使用 nginx upstream 将负载分发到多个后端,配置权重、会话粘性、故障隔离和 Keep-Alive,并能够根据场景选择合适的分发算法。
为什么重要
在 SI 项目中部署两台以上 WAS,主要目的不是提高性能,而是即使一台宕机,
服务仍能继续运行。但 nginx 开源版没有主动健康检查;如果不理解
max_fails/fail_timeout 的含义,就会造成“请求持续发往已宕机服务器”的情况。
此外,upstream Keep-Alive 必须同时具备三项配置才能生效,许多系统因为遗漏
proxy_set_header Connection "",每次请求都会建立新连接。这样会不断积累
TIME_WAIT 套接字,最终耗尽端口。
步骤
- 准备:在 Tomcat(8080)中部署
labhub.war,并在8082 端口启动/opt/lab/samples/labhub-boot.jar。 nginx 使用/root/ng作为 prefix。 - 在
/root/ng/nginx.conf中创建upstream app块, 加入127.0.0.1:8080和127.0.0.1:8082,使 8088 的/代理到该组。log_format中必须包含$upstream_addr,并将访问日志写入/root/ng/logs/access.log。http://127.0.0.1:8088/version必须返回 200。 - 发送20 次请求,然后将访问日志复制到
/root/ng/rr.log。 日志中必须记录至少 2 个不同的 upstream 地址。 - 为
127.0.0.1:8080设置weight=3并 reload, 清空访问日志,发送40 次请求,再复制到/root/ng/weight.log。 发往 8080 的请求数应在 28~32 次之间。 - 将分发方式改为
ip_hash并 reload,清空日志,发送20 次请求后, 复制到/root/ng/iphash.log。 日志中应当只记录一种 upstream 地址。 - 移除
ip_hash(配置文件中不得残留), 为两台服务器都设置max_fails=2 fail_timeout=10s。 然后停止 8082 进程并发送 10 次请求。 10 次请求必须全部返回 200。 - 配置 upstream Keep-Alive:在
upstream块中设置keepalive 32;, 在 location 中设置proxy_http_version 1.1;和proxy_set_header Connection "";。 三项缺一不可。 - 在
upstream块中加入least_conn;,并通过语法检查。 - 编写
/root/ng/lb.md。针对라운드로빈、가중치、ip_hash、least_conn四种方式,分别说明何时应使用以及何时不应使用。 必须出现单词세션,全文至少 400 字。
参考
- 清空日志:
> /root/ng/logs/access.log(无需 reload) - 分阶段快照:
cp /root/ng/logs/access.log /root/ng/rr.log - 统计各 upstream 的请求数:
awk '{...}' access.log | sort | uniq -c - 停止进程:
pkill -f labhub-boot.jar - 常见错误 1:同时使用
ip_hash和weight,却仍期望按权重分发。 - 常见错误 2:遗漏 Keep-Alive 三项配置中的
proxy_set_header Connection "";。 即使升级为 HTTP/1.1,遗漏它也会使连接在每次请求后断开。 - 常见错误 3:把
least_conn;写在 location 中。必须放在upstream块内。
配置 upstream 组
在 /root/ng/nginx.conf 中创建 upstream app 块,
加入 127.0.0.1:8080 和 127.0.0.1:8082,使 8088 的 / 代理到该组。
log_format 中必须包含 $upstream_addr,并将访问日志写入
/root/ng/logs/access.log。
http://127.0.0.1:8088/version 必须返回 200。
upstream 块应放在 http 上下文中。在 proxy_pass 中像使用 URL 一样使用该名称。不要忘记启动两个后端。
验证轮询分发
发送20 次请求,然后将访问日志复制到 /root/ng/rr.log。
日志中必须记录至少 2 个不同的 upstream 地址。
访问日志中的 upstream 地址变量会显示请求发往哪个后端。发送足够多的请求,再统计日志中唯一地址的数量。
按权重分发
为 127.0.0.1:8080 设置 weight=3 并 reload,
清空访问日志,发送40 次请求,再复制到 /root/ng/weight.log。
发往 8080 的请求数应在 28~32 次之间。
nginx 的加权轮询不是随机算法,而是确定性的。权重比例会直接成为分发比例。
会话粘性
将分发方式改为 ip_hash 并 reload,清空日志,发送20 次请求后,
复制到 /root/ng/iphash.log。
日志中应当只记录一种 upstream 地址。
这种方式会将同一客户端发送到同一后端,常用于把会话保存在 WAS 内存中的旧系统。也要记住,增加或移除服务器时会发生重新分配。
自动排除故障服务器
移除 ip_hash(配置文件中不得残留),
为两台服务器都设置 max_fails=2 fail_timeout=10s。
然后停止 8082 进程并发送 10 次请求。
10 次请求必须全部返回 200。
nginx 开源版没有主动健康检查,只有基于失败次数的被动检查。请实际关闭一个后端,确认服务仍能继续运行。
upstream Keep-Alive
配置 upstream Keep-Alive:在 upstream 块中设置 keepalive 32;,
在 location 中设置 proxy_http_version 1.1; 和 proxy_set_header Connection "";。
三项缺一不可。
三项必须一起配置才能生效。只要缺少一项,每次请求就会建立新连接。尤其要注意 Connection 请求头的处理方式。
最少连接方式
在 upstream 块中加入 least_conn;,并通过语法检查。
请思考,在请求处理时间差异很大的服务中,它为何优于轮询。
整理分发算法的选择标准
编写 /root/ng/lb.md。针对 라운드로빈、가중치、ip_hash、least_conn
四种方式,分别说明何时应使用以及何时不应使用。
必须出现单词 세션,全文至少 400 字。
只写每种方式的优点还称不上文档。还应写明何时不该使用,日后才能据此作出判断。