nginx 常见案例
Nginx 的 DNS 缓存问题
参考官方文档:https://www.nginx.com/blog/dns-service-discovery-nginx-plus/
一个非常常见的 nginx 反向代理的配置方式如下:
server {
listen 80;
server_name www.test.com;
location /a {
proxy_set_header Host proxy.test.com;
proxy_pass http://proxy.test.com;
}
location /b {
proxy_set_header Host proxy.test.com;
proxy_pass http://service-b;
}
}
upstream service-b {
# 使用加权轮询(WRR)算法进行负载均衡
server service-b.cluster-1.test.com fail_timeout=1s max_fails=3 weight=90;
server service-b.cluster-2.test.com fail_timeout=1s max_fails=3 weight=10;
keep_alive 30;
}
根据官方介绍,proxy_pass http://proxy.test.com;
这种直接在 proxy_pass
语句中写 DNS 地址的用法有如下问题:
- 如果域名无法解析,Nginx 将无法 start 或者 reload
- 开源的 Nginx 仅在 start/reload 时才会获取该域名的 DNS 记录,然后就一直缓存起来了,记录的 TTL 完全无效!
- 无法指定其他负载均衡算法,仅能使用默认的 RoundRobin 算法
- 无法保持长连接,所有请求结束后连接都被立即关闭
而上述配置中的 proxy_pass http://service-b;
加上 upstream service-b {...}
。
这种配置方式相比前一种,有这几个好处:
- 可以设定在多个 server 上进行负载均衡,使用加权轮询算法调整各 server 的权重
- 可以调整负载均衡算法、超时时间、重试次数等其他参数。
- 可以保持长连接,通过
keepavlie
设定长连接的超时时长
但是它仍然存在 DNS 解析会在 start/reload 时被缓存、以及 DNS 无法解析时会 start/reload 失败的问题!
解决方法一
这种方法是 proxy_pass http://proxy.test.com;
的一个变体,它可以避免 DNS 被 nginx 缓存,TTL 被忽略的问题。
注意:此方法对对使用了
upstream
中的域名无效!
resolver 10.0.0.2 valid=10s;
server {
location / {
set $backend_servers backends.example.com;
proxy_pass http://$backend_servers:8080;
}
}
这种方法通过在 nginx 配置中明确设定 resolver 以及 valid=10s
,使 nginx 每 10s 检查下 TTL 是否过期,过期则重新进行解析。
解决方法二
在 DNS 出现变更时,手动或自动地 reload 下 nginx 配置。
解决方法三 - tengine
阿里巴巴对 Nginx 的修改版——Tengine,提供了 ngx_http_upstream_dynamic_module 模块,可以动态解析 upstream 的 DNS 记录。
解决方法四 - 第三方模块
ngx_upstream_jdomain 这个第三方模块支持动态解析 upstream 的 DNS 记录。
解决方法五 - Nginx Pluse
Nginx Plus 支持在 upstream
中进行动态 DNS 解析.
热重启 Nginx Master
如果 lua 代码存在隐患,长期运行的 Nginx Master 可能会遇到内存溢出,为此需要定期重启(比如两三个星期一次):
ps aux | grep nginx
export OLD_MASTER=
# 启动一个新的 master 进程,平滑地启动新的 worker,和旧 worker 一起处理请求
sudo kill -USR2 $OLD_MASTER
# 等待 60s
# 让旧 master 进程优雅关闭所有旧的 worker,然后退出
sudo kill -QUIT $OLD_MASTER
# 再等待 3m,并且注意观察 QPS、错误状态码(499/5xx)、可用率的监控
Nginx 反向代理的排查思路
延迟上升的排查思路
排查状态码:
- 大量 499: 客户端不想等了,直接断开连接。
- 出现 502/504:
- 后端被打垮了,无响应或者只给了部分响应
- DNS 更新不及时,请求到了已经被回收的 ip 地址,导致响应超时
排查系统层面的性能问题:
- 首先确认 CPU/MEM/Network IO/Disk IO 是否达到瓶颈
- 其次,检查 TCP 连接数量监控,是否有异常