以nginx分发hls直播切片为例,对nginx高并发进行优化设置。
以下示例是nginx反代hls直播切片,每个m3u8包含5个ts切片,每个ts切片市场6s左右。本人使用的是4核8G的vps。
- worker_connections
来自deepseek的说法,针对不同配置worker_connections的建议值:
参数项 | 2核4G VPS | 4核8G VPS | 依据 |
---|
worker_processes | 2(匹配核心数) | 4(匹配核心数) | |
worker_connections | 12288(2核×6144) | 24576(4核×6144) | |
tcp_mem | 6M 8M 10M (保守内存分配) | 8M 12M 16M (更高内存支持) | |
文件缓存(open_file_cache) | max=20000 (减少内存占用) | max=40000 (利用更大内存缓存更多文件) | |
2. worker_rlimit_nofile
依据:需与系统级文件描述符限制(fs.file-max)一致,避免因文件句柄耗尽导致服务中断。
取值逻辑:
2核4G:100000(预留内存余量)
4核8G:200000(更大内存允许更高上限
下面的优化,将以2核4G为例。
3. 系统内核优化 (/etc/sysctl.conf
)
# 连接队列优化
net.core.somaxconn = 16384 # 监听队列长度(2核建议值)
net.ipv4.tcp_max_syn_backlog = 32768
net.core.netdev_max_backlog = 32768 # 与tcp_max_syn_backlog保持对齐
# TIME-WAIT优化
net.ipv4.tcp_tw_reuse = 1 # 快速复用TIME-WAIT连接
net.ipv4.tcp_fin_timeout = 30 # 缩短FIN超时
# 内存缓冲区
net.ipv4.tcp_rmem = 4096 87380 6m # 2核4G内存保守分配
net.ipv4.tcp_wmem = 4096 16384 6m
net.ipv4.tcp_mem = 6m 8m 10m # 按4G内存的15%分配
# 连接管理
net.ipv4.tcp_max_tw_buckets = 100000 # 控制TIME-WAIT总量
net.ipv4.tcp_keepalive_time = 300
# 文件描述符
fs.file-max = 1048576 # 系统级总限制
执行命令使修改生效:
sudo sysctl -p
4. 用户资源限制 (/etc/security/limits.conf)
# Nginx运行用户(宝塔默认为www)
www soft nofile 131072
www hard nofile 262144
# 全局后备设置
* soft nofile 65535
* hard nofile 131072
6. 针对timeout的优化
优化连接超时时间,以防止长时间占用连接让vps资源耗尽。
http {
# 请求头超时(默认60s)
client_header_timeout 10s; # 建议值:5~15秒
# 请求体超时(默认60s)
client_body_timeout 10s; # 建议值:5~15秒(HLS无请求体,可缩短)
# 发送响应超时(默认60s)
send_timeout 20s; # 建议值:20~60秒
# 超时后重置连接(默认off)
reset_timedout_connection on; # 强制开启
}
7. keepalive_requests
定义:单个 TCP 连接最多允许处理多少个 HTTP 请求,超过后强制关闭连接。
本质:控制连接的复用次数(生命周期内的总请求数)。
类比:类似于“一根电话线最多允许通话1000次,之后必须换新线”。
keepalive_requests 5000; # 单个连接最多处理500个请求
8. 启用 HTTP/2
多路复用特性可显著减少 TCP 连接数,降低对 keepalive 配置的依赖:
listen 443 ssl http2;
keepalive_timeout:在HTTP/2中仍有效,但仅在连接完全空闲时触发。
keepalive_requests:在HTTP/2中通常被忽略,连接生命周期由协议自身管理。
如果还套了cloudflare CDN,还可以考虑不适用SSL以节省服务器开销,使用reuseport:
listen 80 reuseport; # Linux 3.9+ 端口复用提升性能
server_name _;
9. limit_conn并发连接数优化
limit_conn_zone $binary_remote_addr zone=addr:10m; # 定义共享内存区(10MB)存储IP连接状态
limit_conn addr 6; # 每个IP最多允许8个并发TCP连接
limit_conn_zone用于定义共享内存区域来存储连接状态,这里用$binary_remote_addr作为键,表示客户端的IP地址。zone=addr:10m分配了10MB的内存空间。limit_conn addr 8则是限制每个IP同时活跃的连接数为8。这里的“连接数”指的是同一时间的TCP连接,而不是请求数。每个HTTP请求可能复用同一个连接(在keepalive开启的情况下),但HLS的情况下,由于需要不断获取m3u8和ts,可能会有多个并发连接。
连接数估算
单播放器连接数:通常为 1(m3u8) + N(并行ts下载)。
例如:若播放器并行下载2个 ts 切片,则占用 1+2=3 个连接。
IP连接上限:若 limit_conn addr 6,则单个IP最多支持约 6/3=2 个播放器。
最后要重启nginx使配置生效:
# 根据系统服务管理工具选择命令
systemctl restart nginx # Systemd
配置示例:
server
{
listen 80 reuseport;
server_name www.168itw.com;
index index.php index.html index.htm default.php default.htm default.html;
root /www/wwwroot/www.168itw.com;
client_header_timeout 10; # 客户端请求头超时
client_body_timeout 10; # 客户端请求体超时
send_timeout 15; # 响应超时时间
reset_timedout_connection on; # 超时后重置连接
keepalive_timeout 10; # 保持连接的超时时间
keepalive_requests 5000; # 单个连接最多处理5000个请求
# 限制单个IP的并发连接数
limit_conn perip 6; # 每个IP最多6个连接
}
其中:
keepalive_requests 5000; # 单个连接最多处理5000个请求
# 限制单个IP的并发连接数
limit_conn perip 6; # 每个IP最多6个连接
这是限制IP连接请求的,在后端服务器上可以不用设置。
当 Nginx 作为反向代理时:
- 客户端到 Nginx 的连接:由客户端行为或 Nginx 的 keepalive_timeout 控制。
- Nginx 到后端 的连接:由 proxy_set_header Connection 和 keepalive 配置控制。
反代服务器配置
如果反代服务器需要高频繁高并发的与后端服务器通信,可以使用HTTP/1.1 keepalive连接复用。
nginx的http块中配置upstream backend,以连接复用:
upstream backend {
server backendserver.168itw.com;
keepalive 1000;
}
反代配置:
#PROXY-START/
location /
{
proxy_pass http://backend;
proxy_set_header Host backendserver.168itw.com;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header REMOTE-HOST $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_http_version 1.1; # 强制使用 HTTP/1.1
proxy_set_header Connection ""; # 清除 Connection 头
proxy_connect_timeout 5s; # 与后端建立TCP连接的超时时间(建议5-10秒)
proxy_send_timeout 10s; # 向后端发送请求数据的超时时间(建议10-15秒)
proxy_read_timeout 10s; # 从后端读取响应数据的超时时间(建议15-30秒)
# proxy_hide_header Upgrade;
#Persistent connection related configuration
add_header X-Cache $upstream_cache_status;
}
#PROXY-END/
10. 针对元数据的优化
# 在 server 级别开启并定义缓存池
# 所有 location 共享这个大小为 5000 的缓存池
open_file_cache max=5000 inactive=30s;
open_file_cache_errors on;
open_file_cache_min_uses 1; # 对所有文件都生效,第一次访问即缓存
# 针对 M3U8 文件的 location 块
location ~ \.m3u8$ {
# 关键:为 M3U8 设置一个很短的有效性检查周期
# 比如切片时长是 5s,这里就设置为 5s
open_file_cache_valid 5s;
add_header Cache-Control no-cache;
}
# 针对 TS 文件的 location 块
location ~ \.ts$ {
# 关键:为 TS 设置一个非常长的有效性检查周期
# 因为 TS 文件一旦生成就不会改变,没必要频繁检查
# 设置为 300s 小时甚至更长,可以极大地减少不必要的系统调用
open_file_cache_valid 300s;
}