负载均衡就是把流量分配到多台服务器上,让资源利用更充分、吞吐量更大,也避免单台机器被打挂。Nginx 两种都能做:七层(HTTP)开箱即用,四层(TCP/UDP)靠 stream 模块。这篇在 nginx:1.28 容器里把两种负载均衡同时跑起来——同一组后端,两个入口,看它们的分发行为和能力边界差在哪。

实验环境

  • Docker 容器 nginx:1.28-alpine(nginx/1.28.3,nginx -V 确认编译了 --with-stream,2026-09 实测)。
  • 两个”后端”:同容器内 8081 端口返回 APP-ONE,8082 端口返回 APP-TWO——响应体带身份,分发到谁一目了然。
  • 演示配置用 worker_processes 1:多 worker 下每个进程有独立的轮询游标,快速连发时流量会集中到各 worker 的首个后端,单 worker 让轮询效果最直观。

七层负载均衡:能看内容,才能按内容路由

http 块里的标准三件套——upstream 后端组、入口 server、代理转发:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
http {
upstream myapp1 {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 8097; # 容器里 80 已被占用,物理机部署换回 80 即可
location / {
proxy_pass http://myapp1;
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 是反向代理的常规动作:把原始 Host、客户端真实 IP(X-Real-IP)和转发链(X-Forwarded-For)传给后端,后端日志才能记录真实来源。

验证点:连续请求 /,分发按默认轮询(round-robin)在两台后端间交替:

配图1

七层真正的杀手锏是按内容路由——加一个 location,把 /api/ 的流量固定到指定后端:

1
2
3
location /api/ {
proxy_pass http://127.0.0.1:8081/;
}

验证点:请求 /api/x 恒定命中 APP-ONE,其余路径继续参与轮询——URL 级的路由,只有解析了 HTTP 的七层才做得到:

配图2

四层负载均衡:stream 模块按连接转发

stream 块与 http 块平级,配置形状几乎一样:

1
2
3
4
5
6
7
8
9
10
11
stream {
upstream backend {
server 127.0.0.1:8081;
server 127.0.0.1:8082;
}
server {
listen 12345;
proxy_pass backend;
proxy_next_upstream off;
}
}

listen 12345 监听的是 TCP 端口,Nginx 不解析内容,把整条 TCP 连接原样转发给 backend 组;proxy_next_upstream off 关闭失败重试——对数据库、消息队列这类非幂等协议,重试等于重复执行,必须关。

验证点:往 12345 端口发 HTTP 请求(TCP 层它就是普通流量),分发在两台后端间进行:

配图3

注意一个细节:四层的分发粒度是连接——一条连接建立时选定后端,之后这条连接里的所有请求都走它;七层按请求分发,同一连接里的每个 HTTP 请求都可换后端。

四层与七层的边界

实测下来两条分界线很清楚:

  • 能力:四层只看 IP 和端口,转发快、协议无关(MySQL、Redis、SSH 都能分);七层解析 HTTP,能按 URL、Header、Cookie 做精细路由——实测里 /api/ 固定到指定后端,四层架构上就做不到。
  • 开销:七层要解析、改写 HTTP 头,多消耗 CPU;四层是内核级转发的思路,单机吞吐上限更高。TLS 终结也有差异:七层(HTTPS)由 Nginx 解密后转发明文,四层只能把加密流原样转发或配 stream_ssl。

两个入口也可以同时存在于一个 Nginx 实例里——本篇实验就是这么跑的,stream 和 http 各管各的端口,互不干扰。

注意事项

  • stream 不是第三方模块:1.9.0 起官方内置,编译时带 --with-stream 即可;官方 Docker 镜像已默认包含,nginx -V 可确认。
  • 非幂等协议关掉重试:stream 场景下 proxy_next_upstream off 要形成习惯,连接转发的失败重试对数据库类流量是灾难。
  • 七层转发记得传真实 IP:漏配 X-Real-IP/X-Forwarded-For,后端看到的永远是 Nginx 的 IP,限流、审计全部失真。
  • 多 worker 观察轮询会失真:每个 worker 进程独立维护轮询游标,快速连发时流量偏向各 worker 的首个后端,验证负载策略时固定 worker_processes 1 或加大样本量。

小结

回到开头的场景:把流量摊到多台机器上——Nginx 一套配置搞定两种负载均衡。实测的分界很直观:七层看得见 URL,能做 /api/ 走专门后端这种内容路由,代价是解析开销;四层只认连接,快、协议无关,数据库和消息队列的流量找它。记住三件事——stream 平级于 http、非幂等流量关 proxy_next_upstream、转发时带上真实 IP——两种负载均衡就能各就各位。


本文由作者 2020-2024 年间的 CSDN 博客文章重构而来,原发布于 CSDN。