在Ubuntu服务器上配置Nginx反向代理和负载均衡,核心就是通过upstream模块把多台后端应用服务器串联起来,再配合health_check机制自动剔除故障节点。整个配置流程分为三步:安装Nginx、编写upstream和proxy_pass规则、设置健康检查策略。下面直接给你完整的操作方案和原理拆解。
一、Ubuntu环境下Nginx的安装与基础准备
先确保系统是Ubuntu 20.04或22.04,执行以下命令安装Nginx:
sudo apt update sudo apt install nginx -y
安装完成后,确认Nginx版本是否支持被动健康检查(默认就支持)和主动健康检查模块(需要编译安装nginx_upstream_check_module或使用开源版本的nginx-healthcheck-plugin)。对于大多数场景,Nginx自带的被动健康检查(fail_timeout + max_fails)已经够用。验证安装:
nginx -v
确认版本号后,进入配置目录:
cd /etc/nginx/
Ubuntu的Nginx主配置文件是nginx.conf,但实际业务配置建议放在/etc/nginx/conf.d/目录下新建独立文件,比如proxy_loadbalance.conf,方便管理和维护。
二、upstream反向代理与负载均衡的核心配置
打开或新建配置文件,在http块内编写upstream定义。这是整个反向代理的心脏部分:
upstream backend_servers {
# 负载均衡策略:默认轮询(round-robin),也可选least_conn(最少连接)、ip_hash(IP哈希)
least_conn;
server 192.168.1.101:8080 weight=5 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.103:8080 weight=2 max_fails=3 fail_timeout=30s;
# 备用服务器,主节点全挂时才启用
server 192.168.1.104:8080 backup;
}
这里有几个关键参数需要理解:weight是权重,数值越大分配的请求越多;max_fails表示在fail_timeout时间内失败多少次就认为该节点不可用;fail_timeout是判定节点不可用的时间窗口,同时也是节点恢复后重新尝试的间隔。least_conn策略特别适合后端服务器性能不均的场景,它会把新请求分配给当前连接数最少的节点。
接下来在server块中配置反向代理:
server {
listen 80;
server_name yourdomain.com;
location / {
proxy_pass http://backend_servers;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# 超时设置,防止后端响应慢导致Nginx阻塞
proxy_connect_timeout 10s;
proxy_send_timeout 30s;
proxy_read_timeout 60s;
}
}
proxy_set_header这几行非常重要,它把客户端的真实IP和协议信息传递给后端,否则后端看到的全部是Nginx的内网IP。超时参数根据业务调整,如果是API接口建议proxy_read_timeout设长一些。
三、健康检查的两种实现方式详解
Nginx的健康检查分被动和主动两种。被动健康检查是Nginx原生支持的,通过max_fails和fail_timeout自动实现。当Nginx转发请求到某个后端节点,如果连续失败max_fails次,就在fail_timeout时间内不再给该节点分配请求。这是最简单也最常用的方式。
主动健康检查需要额外模块支持。如果你用的是开源的tengine或者编译了healthcheck模块,可以这样配置:
upstream backend_servers {
server 192.168.1.101:8080 max_fails=3 fail_timeout=30s;
server 192.168.1.102:8080 max_fails=3 fail_timeout=30s;
# 主动健康检查配置
check interval=5000 rise=2 fall=3 timeout=3000 type=http;
check_http_send "GET /health HTTP/1.0\r\n\r\n";
check_http_expect_alive http_2xx http_3xx;
}
check interval=5000表示每5秒检测一次;rise=2表示连续2次成功才认为节点恢复;fall=3表示连续3次失败才标记为不可用;type=http表示用HTTP方式检测;check_http_send是发送的探测请求,check_http_expect_alive定义了哪些响应码算正常。这种方式的优势是不依赖真实用户请求,能更快发现故障。
如果你没有编译healthcheck模块,也可以用一个替代方案:在后端应用自己暴露一个/health接口返回200,然后通过Nginx的被动检查机制来间接实现。或者用cron脚本定期curl后端接口,失败则通过API动态修改Nginx upstream(需要配合openresty或lua模块)。
四、配置验证与重载的正确姿势
每次改完配置文件,必须先测试语法再重载,否则一个括号错误就会导致Nginx挂掉:
sudo nginx -t
看到"syntax is ok"和"test is successful"才能执行重载:
sudo systemctl reload nginx
注意是reload不是restart,reload是平滑重载,不会中断现有连接。如果你需要彻底重启(比如改了监听端口),才用restart。
五、日志监控与故障排查实战
负载均衡跑起来之后,日志是你的眼睛。Nginx的访问日志和错误日志默认在/var/log/nginx/目录下。建议在upstream级别开启日志:
upstream backend_servers {
server 192.168.1.101:8080;
server 192.168.1.102:8080;
# 记录每次转发到哪个节点
# 需要在http块中配置log_format
}
在http块中定义带upstream信息的日志格式:
log_format main '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'upstream: $upstream_addr '
'upstream_status: $upstream_status '
'request_time: $request_time';
access_log /var/log/nginx/access.log main;
$upstream_addr会记录实际转发到的后端IP和端口,$upstream_status记录后端返回的状态码,$request_time记录整个请求耗时。通过这些字段你可以清楚看到流量分配是否均衡、哪个节点响应慢、哪个节点在报错。
日常排查命令:查看哪些后端节点被标记为不可用:
sudo nginx -T 2>/dev/null | grep -A 20 "upstream"
实时监控错误日志:
tail -f /var/log/nginx/error.log
如果发现某个节点频繁被踢出,先检查后端服务本身是否稳定,再检查网络连通性(ping、telnet端口),最后看是不是weight设置不合理导致某节点过载。
六、进阶优化:会话保持与SSL终结
如果你的后端应用需要会话保持(比如用户登录后需要一直访问同一台服务器),把least_conn改成ip_hash:
upstream backend_servers {
ip_hash;
server 192.168.1.101:8080;
server 192.168.1.102:8080;
}
ip_hash根据客户端IP计算哈希值,同一IP始终路由到同一后端。但要注意,如果后端节点增减,哈希会重新分配,可能导致大量会话丢失。生产环境更推荐用Redis共享session或者在应用层做无状态设计。
SSL终结也是Nginx反向代理的常见场景,在server块中加上SSL配置:
server {
listen 443 ssl;
server_name yourdomain.com;
ssl_certificate /etc/nginx/ssl/yourdomain.crt;
ssl_certificate_key /etc/nginx/ssl/yourdomain.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
location / {
proxy_pass http://backend_servers;
# ...其余proxy配置同上
}
}
SSL证书可以用certbot免费申请,配置好后HTTP请求建议301跳转到HTTPS,保证传输安全。
七、常见踩坑点与经验总结
第一,不要把所有后端服务器都设成相同weight,如果机器配置不同,一定要按性能比例分配权重。第二,fail_timeout不要设太短,比如设成5秒,网络抖动一下就把节点踢了,流量全压到剩余节点反而更危险,建议30秒起步。第三,如果后端是WebSocket应用,必须加这几行:
proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
否则WebSocket连接会直接断开。第四,生产环境建议至少三台后端服务器,两台做负载一台做backup,单点故障风险太高。第五,定期用ab或wrk做压力测试,验证负载均衡是否真正生效,而不是只看配置觉得没问题。
总结一下,Ubuntu上Nginx反向代理和负载均衡的配置并不复杂,核心就是upstream定义加proxy_pass转发,健康检查用被动机制基本够用,主动检查需要额外模块支持。把日志配好、参数调对、测试做足,这套方案在中小型项目里完全能扛住日均百万级请求。
