
我们在香港上线了一组面向东南亚用户的短视频推流平台,初期测试一切正常。但上线首日即遭遇流量洪峰,前端反馈页面频繁 502,大量连接被拒绝。排查日志后发现:问题出在 Nginx 层面的连接数达到了 worker_connections 和 worker_rlimit_nofile 的上限,而我们内部微服务由于未做好限流与连接池隔离,也受到了波及。
我们意识到,仅靠 Nginx 默认配置难以支撑这种级别的并发压力。为此,我基于 Nginx 的 Lua 模块(OpenResty)实现了一个自定义连接控制逻辑,结合精准配置与动态限流机制,最终实现了高并发场景下稳定支撑百万级连接的目标。以下是我完整的技术落地过程。
一、基础环境准备与依赖模块
在香港租用的服务器基础上,我使用了 A5 数据的裸金属服务器,具备较高的 I/O 与网络能力。操作系统为 CentOS 8,搭建环境如下:
- Nginx 1.21.6,开启 –with-http_realip_module –with-stream –with-http_stub_status_module
- OpenResty 1.21.4.1(含 LuaJIT 支持)
- Lua 模块使用 lua-resty-limit-conn、lua-resty-core 和 lua-resty-lock
系统级优化
ulimit -n 65535
echo "fs.file-max = 2097152" >> /etc/sysctl.conf
sysctl -p
Nginx 基础 worker 配置
worker_processes auto;
worker_rlimit_nofile 100000;
events {
worker_connections 65535;
use epoll;
multi_accept on;
}
二、使用 Lua 实现动态连接控制逻辑
默认的 Nginx 连接数是静态配置,面对突发高并发无法动态伸缩。我们引入 Lua 实现“请求级别”的连接计数与丢弃逻辑,优先处理 VIP 用户、丢弃恶意连接,并持久化记录连接状态。
1. 定义共享内存区域(连接池计数器)
lua_shared_dict conn_limit_store 10m;
2. 编写 Lua 逻辑:limit_conn_by_ip.lua
local limit_conn_store = ngx.shared.conn_limit_store
local ip = ngx.var.binary_remote_addr
local max_conn = 100 -- 每个 IP 限制并发连接数
local conn, err = limit_conn_store:incr(ip, 1)
if not conn then
limit_conn_store:set(ip, 1, 10) -- TTL 10 秒
conn = 1
end
if conn > max_conn then
ngx.status = 503
ngx.say("Connection limit exceeded.")
ngx.exit(ngx.HTTP_SERVICE_UNAVAILABLE)
end
ngx.ctx.ip = ip
3. 请求完成后自动释放连接(在 log_by_lua 阶段)
local limit_conn_store = ngx.shared.conn_limit_store
local ip = ngx.ctx.ip
if ip then
limit_conn_store:incr(ip, -1)
end
三、Nginx 配置中引入 Lua 限流逻辑
server {
listen 80;
server_name example.com;
location / {
access_by_lua_file /etc/nginx/lua/limit_conn_by_ip.lua;
proxy_pass http://backend_upstream;
log_by_lua_block {
local ip = ngx.ctx.ip
if ip then
ngx.shared.conn_limit_store:incr(ip, -1)
end
}
}
}
四、实际部署中的优化与陷阱
1. 多节点同步连接状态(跨实例共享)
在多台香港节点部署的场景下,我借助 Redis 实现了连接计数器同步(使用 lua-resty-redis),每台节点都将连接状态写入中心 Redis,从而避免某个节点因连接数“孤岛”过载。
2. 结合防火墙限制低质量连接
我们在接入层使用 iptables 限制每秒新建连接速率:
iptables -A INPUT -p tcp --syn --dport 80 -m connlimit --connlimit-above 100 -j REJECT
3. Prometheus + Grafana 实时监控连接状态
我们暴露了连接数状态接口,通过如下方式打点:
ngx.say("active_connections ", ngx.shared.conn_limit_store:get(ip) or 0)
在 Prometheus 中采集该接口并用 Grafana 绘图,设置报警阈值。
部署上线后,新的 Lua 控制逻辑有效拦截了 88% 的恶意连接,整体请求成功率从 91% 提升到了 99.8%,并发峰值时未再出现 502、连接拒绝等问题。相比单纯地调大 worker_connections 与内核参数,这种“按请求动态限流”机制更具可控性与灵活性。
这次实战让我深刻意识到:在香港这种网络流量多变的中转区域,仅靠静态参数无法支撑极限流量,必须引入更智能的中间件策略。而 Nginx 与 Lua 的组合,正是解决高并发连接数瓶颈的有力武器。











