在现代AI基础设施中,高性能的模型服务通常不只依赖标准的HTTP协议(L7)。例如,gRPC服务、Redis缓存层、或自定义的高速二进制协议通常需要进行四层(L4,TCP/UDP)的负载均衡和代理。Nginx凭借其强大的stream模块,可以轻松胜任这一任务,成为L4流量的核心路由器。
Contents
1. Stream模块概述与必要性
Nginx默认主要处理HTTP流量。但为了处理纯TCP或UDP流量,我们需要启用stream模块。如果你的Nginx是通过源码编译安装,需要确保在配置时加入了–with-stream参数。对于大多数使用包管理器安装的现代Nginx版本,stream模块通常已内置。
四层代理的优势在于:
1. 协议无关性: 代理任何基于TCP或UDP的流量,无需解析应用层协议(如HTTP头部)。
2. 高性能: 处理速度更快,延迟更低,适用于高吞吐量的模型推理服务。
3. 服务分离: 可以在统一的入口端口上对不同类型的后端服务进行分流。
2. Nginx Stream配置实操
与L7配置不同,L4配置需要在主配置文件(通常是/etc/nginx/nginx.conf)的根级别定义一个独立的stream上下文,它与http上下文是并列关系。
步骤一:配置Upstream后端服务
首先,定义我们的AI推理服务集群。假设我们有两个推理服务实例运行在8001和8002端口上。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37 # /etc/nginx/nginx.conf 核心配置
worker_processes auto;
# 定义 stream 上下文,与 http 上下文并列
stream {
# 1. 定义后端服务器集群 (Upstream)
upstream inference_tcp_backends {
# 负载均衡算法:默认为 round-robin
server 127.0.0.1:8001 weight=3; # 权重更高,分发更多流量
server 127.0.0.1:8002;
# 可以在此处添加健康检查:
# server 127.0.0.1:8003 max_fails=3 fail_timeout=30s;
}
# 2. 定义前端监听服务 (Server)
server {
listen 9000; # 监听 9000 端口,接收 TCP 流量
proxy_pass inference_tcp_backends; # 转发到后端集群
# L4 相关参数配置
proxy_timeout 30s; # 客户端与后端连接的超时时间
proxy_connect_timeout 5s; # Nginx连接后端服务器的超时时间
}
# 示例:如果是 UDP 代理 (例如 DNS 或某些数据采集)
# server {
# listen 53 udp;
# proxy_pass dns_servers;
# }
}
http {
# ... L7 HTTP 配置
}
步骤二:启动测试环境
为了验证配置,我们创建一个简单的Python脚本,模拟两个监听不同端口的TCP推理服务器。
首先,确保安装了python环境,并保存以下代码为 tcp_servers.py:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import socket
import threading
import time
def run_server(port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('127.0.0.1', port))
s.listen(5)
print(f"[SERVER {port}] TCP server started at 127.0.0.1:{port}")
while True:
try:
conn, addr = s.accept()
# time.sleep(0.1) # 模拟处理延迟
data = conn.recv(1024).decode().strip()
response = f"[Server {port}] Received: {data}. Time: {time.time()}"
print(f"-> Handling request on {port}: {data}")
conn.sendall(response.encode())
conn.close()
except Exception as e:
print(f"Error on server {port}: {e}")
# 启动两个后端服务
tcp_ports = [8001, 8002]
for port in tcp_ports:
threading.Thread(target=run_server, args=(port,)).start()
运行Python服务器:
1
2
3 python3 tcp_servers.py
# [SERVER 8001] TCP server started at 127.0.0.1:8001
# [SERVER 8002] TCP server started at 127.0.0.1:8002
步骤三:测试L4代理转发
重启Nginx并使用netcat (nc) 或 telnet 测试Nginx监听的9000端口。
1
2
3
4
5
6
7
8
9
10
11
12
13
14 # 重启Nginx加载新配置
sudo nginx -s reload
# 第一次请求,应到达8001 (因为8001权重更高)
echo "Inference Request A" | nc 127.0.0.1 9000
# 第二次请求,应到达8001
echo "Inference Request B" | nc 127.0.0.1 9000
# 第三次请求,应到达8001
echo "Inference Request C" | nc 127.0.0.1 9000
# 第四次请求,应到达8002 (权重分配生效)
echo "Inference Request D" | nc 127.0.0.1 9000
根据Python服务器的输出,你可以看到流量根据Nginx配置的Round-Robin策略和权重被正确地转发到了不同的后端端口。
3. 高级Stream配置技巧
A. 基于源IP的哈希负载均衡 (会话保持)
对于需要保持客户端连接状态的推理服务(例如,需要特定Session ID),可以使用hash负载均衡算法:
1
2
3
4
5 upstream sticky_backends {
hash $remote_addr consistent; # consistent确保在增减服务器时影响最小
server 127.0.0.1:8001;
server 127.0.0.1:8002;
}
B. L4 SSL/TLS Termination
如果流量是加密的,Nginx的stream模块也可以进行TLS终止(即解密客户端连接,再以明文或再次加密的方式转发给后端)。
1
2
3
4
5
6 server {
listen 9443 ssl;
ssl_certificate /path/to/cert.pem;
ssl_certificate_key /path/to/key.pem;
proxy_pass inference_tcp_backends;
}
通过配置stream模块,Nginx不仅是L7的代理神器,也能轻松成为AI基础设施中不可或缺的L4高性能流量分配器。
汤不热吧