作为一名长期在生产环境使用Nginx的运维工程师,我经常需要向团队新人解释Nginx的核心工作机制。今天我就用最直白的方式,拆解Nginx反向代理和负载均衡的实现原理,这些都是我多年踩坑后总结的实战经验。
Nginx的反向代理功能本质上是在客户端和后端服务器之间扮演"中间人"角色。当客户端发起请求时,Nginx会先与客户端建立TCP连接,然后根据配置选择合适后端服务器,修改请求头后转发请求。整个过程涉及11个精细化的处理阶段,每个阶段都有特定的用途和优化空间。
提示:理解这些底层机制对排查线上问题至关重要。上周我们一个API接口响应慢,就是通过分析Nginx的CONTENT阶段定位到后端服务瓶颈。
Nginx处理每个HTTP请求会经历11个有序阶段:
code复制1. POST_READ - 刚读完请求头,适合做全局限流
2. SERVER_REWRITE - server块内的rewrite规则
3. FIND_CONFIG - 匹配location(核心路由逻辑)
4. REWRITE - location中的rewrite规则
5. POST_REWRITE - 检查rewrite结果
6. PREACCESS - 限流预处理(如limit_req)
7. ACCESS - 权限控制(auth_basic等)
8. POST_ACCESS - 权限后处理
9. PRECONTENT - try_files指令处理
10. CONTENT - 核心内容生成(proxy_pass在此阶段)
11. LOG - 记录访问日志
关键点:反向代理实际发生在第10阶段(CONTENT),由ngx_http_proxy_module模块负责。这意味着前面9个阶段的处理都不会影响后端服务器,所有rewrite、限流、认证都在Nginx本地完成。
Nginx与客户端、后端分别维护独立的TCP连接:
code复制客户端 ←→ Nginx (连接A) ←→ 后端服务 (连接B)
这种设计带来两个重要特性:
这是我常用的优化配置:
nginx复制upstream backend {
server 10.0.0.1:8080;
keepalive 32; # 连接池大小
}
server {
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
}
}
经验:生产环境中,keepalive值建议设为后端服务器数量的3-5倍。我们曾经因为设置过小导致大量TCP握手开销。
Nginx的缓冲功能是应对慢客户端的利器:
nginx复制location / {
proxy_buffering on;
proxy_buffer_size 4k; # 响应头缓冲区
proxy_buffers 8 16k; # 响应体缓冲区
proxy_busy_buffers_size 32k;
proxy_temp_path /var/nginx/temp;
}
工作原理:
踩坑记录:曾经有个图片服务因为proxy_buffers设置过小,导致大量磁盘IO。调整后CPU使用率下降40%。
这是Nginx最核心的负载均衡算法,特点是:
算法实现伪代码:
code复制初始化:
每个节点current_weight = 0
总权重total_weight = 所有节点权重和
每次选择:
1. 所有节点current_weight += weight
2. 选择current_weight最大的节点
3. 被选节点current_weight -= total_weight
实际案例:
假设有三个后端:
请求分配序列会是:A,B,C,A,A,B,A,C,B,A(10次请求正好符合5:3:2的比例)
适用于需要会话保持的场景:
nginx复制upstream backend {
ip_hash;
server 10.0.0.1;
server 10.0.0.2;
}
实现原理:
注意:增减节点会导致大部分会话重新分配,不适合频繁扩缩容的场景。
适合处理时间差异大的场景:
nginx复制upstream backend {
least_conn;
server 10.0.0.1 weight=5;
server 10.0.0.2 weight=3;
}
算法核心公式:
code复制选择 active_connections/weight 最小的节点
优势:能自动将请求导向压力较小的后端,特别适合长连接服务。
Nginx原生支持基于失败计数的健康检查:
nginx复制upstream backend {
server 10.0.0.1 max_fails=3 fail_timeout=30s;
server 10.0.0.2 max_fails=3 fail_timeout=30s;
server 10.0.0.3 backup; # 备用节点
}
工作机制:
使用nginx_upstream_check_module:
nginx复制upstream backend {
server 10.0.0.1;
server 10.0.0.2;
check interval=3000 rise=2 fall=3 timeout=2000 type=http;
check_http_send "HEAD /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
参数说明:
nginx复制upstream backend {
# 后端定义
server 10.0.0.1:8080 weight=5 max_fails=3 fail_timeout=30s;
server 10.0.0.2:8080 weight=3 max_fails=3 fail_timeout=30s;
# 负载均衡算法
least_conn;
# 连接池
keepalive 32;
keepalive_timeout 60s;
# 健康检查
check interval=5000 rise=2 fall=3 timeout=1000 type=http;
}
server {
listen 80;
location / {
proxy_pass http://backend;
# 连接设置
proxy_http_version 1.1;
proxy_set_header Connection "";
# 超时控制
proxy_connect_timeout 3s;
proxy_read_timeout 10s;
proxy_send_timeout 10s;
# 缓冲设置
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 16k;
# 头信息传递
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
建议监控以下Nginx指标:
我们使用Prometheus+Grafana搭建的监控看板,可以实时发现负载均衡不均的问题。
可能原因:
排查步骤:
典型优化手段:
最近我们通过优化keepalive_timeout从默认75s降到15s,减少了30%的内存使用。