Nginx需启用stream模块并配置upstream keepalive实现MySQL/Redis连接复用,核心是每个worker缓存空闲后端连接(如keepalive 32),跳过TCP握手与认证开销,而非使用HTTP上下文的keepalive_timeout。

Nginx 本身不直接代理 MySQL 或 Redis 协议——它原生只支持 HTTP/HTTPS、gRPC、FastCGI 和(自 1.9.0 起)TCP/UDP 流量的 四层代理。若要让 Nginx 为 MySQL 或 Redis 提供连接复用能力,必须启用 stream 模块,并在 stream 上下文中配置 keepalive,而非 HTTP 上下文中的 keepalive_timeout。
MySQL/Redis 场景需用 stream 模块的 keepalive
HTTP 的 keepalive 是面向请求-响应周期的复用,而 MySQL/Redis 是长连接、无明确“请求结束”语义的二进制协议。Nginx 对这类服务只能做 TCP 层转发,因此必须使用 stream 块,并依赖其专用的连接池机制:
-
keepalive(在 upstream 内):定义每个 worker 进程可缓存到后端(如 MySQL 或 Redis)的空闲连接数,单位是“连接数”,不是超时时间 - 该指令仅在
stream { upstream { ... } }中有效,与 HTTP 的keepalive_timeout完全无关 - 未配置时,每次客户端连接都会新建后端连接,造成 TCP 握手 + 认证开销,尤其在短连接高频访问场景下显著拖慢响应
正确配置示例(以 Redis 为例)
在 /etc/nginx/nginx.conf 的顶层添加 stream 块:
stream {
upstream redis_backend {
server 127.0.0.1:6379;
keepalive 32; # 每个 worker 缓存最多 32 条空闲连接
}
<pre class="brush:php;toolbar:false;">server {
listen 6380;
proxy_pass redis_backend;
proxy_timeout 10s;
proxy_responses 1; # Redis 单次响应通常一个包,设为 1 可早释放连接
}}
-
keepalive 32表示每个 Nginx worker 进程最多维护 32 条已认证、空闲的到 Redis 的连接;新客户端请求会优先复用这些连接,跳过 TCP 三次握手和 AUTH 步骤 -
proxy_timeout控制空闲连接保活时长,超时后自动关闭连接(非 keepalive_timeout) - 务必确认 Nginx 已编译启用
--with-stream模块(宝塔默认不含,需手动编译或选装流模块版)
MySQL 类似但需注意协议兼容性
MySQL 同样走 stream,但要注意:
- MySQL 客户端首次连接需完成 handshake、SSL negotiation、authentication,这些步骤无法跳过;keepalive 复用的是已完成认证的连接,所以后续请求直通,省去全部握手流程
- 若应用层使用连接池(如 PHP PDO 的 persistent connection),Nginx stream keepalive 是叠加优化,而非替代
- 避免将
keepalive值设得过大(如 >64):MySQL 默认max_connections有限,过多空闲连接可能提前耗尽后端连接数 - 建议搭配
proxy_buffer_size 4k;和proxy_buffering on;(stream 模块支持缓冲)减少小包往返
验证是否生效
不能靠 curl 或浏览器测,需用真实客户端观察行为:
- 用
redis-cli -p 6380连接后执行多次PING,用tcpdump -i lo port 6379观察:复用时只有数据包,无 SYN/FIN - 查 Nginx 日志(需开启
log_formatfor stream)或监控nginx_stream_upstream_connections_total{state="idle"}(Prometheus exporter) - 对比开启前后,相同压测 QPS 下的平均延迟下降幅度(典型提升 15–40%,取决于网络 RTT 和后端认证耗时)



















