一、业务场景与核心痛点
在本地部署大模型推理服务的生产场景中,GPU算力、显存资源是核心瓶颈,无法支撑无限并发请求。笔者本次落地的业务场景如下:
-
本地私有大模型服务:单实例最大安全并发数10,超并发会导致显存溢出、推理超时、服务宕机
-
兜底容灾方案:阿里云通义千问 Qwen3 三方API,作为高并发流量兜底
-
核心诉求:低并发流量优先走本地GPU推理(低成本、低延迟),并发超过时,超额请求自动无缝切换至三方API,全程业务无感知、零报错、不丢请求
传统Nginx反向代理仅能实现基础的负载均衡、静态限流,存在明显短板,无法满足精细化的AI服务流量调度需求:
-
原生
max_conns+error_page降级方案存在1秒队列等待延迟,切换不及时 -
无法实时精准统计全局活跃并发数,流量切换存在误差
-
不支持动态流量调度,无法适配大模型固定并发上限的业务特性
基于此,本文采用 OpenResty + Lua 方案,通过Lua脚本介入Nginx全请求生命周期,实现毫秒级精准并发统计、无延迟自动降级、统一接口透传,完美适配大模型推理服务的流量调度场景。
二、方案选型:原生Nginx VS OpenResty Lua
| 对比维度 | 原生Nginx方案 | OpenResty+Lua方案 |
|---|---|---|
| 降级延迟 | 存在1s队列超时等待,切换滞后 | 请求接入瞬间判断,0延迟切换 |
| 并发精度 | 基于队列机制,计数存在偏差 | 共享内存原子计数,精准个位数统计 |
| 灵活性 | 仅支持错误码被动降级,逻辑固化 | 支持自定义阈值、动态路由、参数兼容 |
| 业务侵入性 | 无侵入 | 纯网关层实现,零业务代码修改 |
| 可观测性 | 仅日志统计,无实时监控 | 支持实时并发查询、精准日志统计 |
核心优势总结:OpenResty 基于Nginx内核,兼容所有Nginx配置,同时通过Lua脚本实现业务化流量调度,是AI大模型网关流量治理的最优轻量化方案。
三、整体架构设计
为实现流量无缝切换,笔者统一标准化双端服务接口,保证流量切换对业务完全透明:
-
主服务(低并发):
10.10.1.xxx:18001,模拟本地私有大模型服务,最大并发30 -
备服务(高并发兜底):
10.10.1.xxx:18002,封装阿里云Qwen3三方API,统一OpenAI兼容接口格式 -
统一入口网关:OpenResty 对外暴露
13008端口,业务仅需调用该统一地址
核心流程:请求接入网关 → Lua脚本原子统计全局并发 → 并发≤10走本地服务 → 并发>10自动路由至三方封装服务 → 请求结束自动回收并发计数。
四、核心技术实现
4.1 三方API统一封装
阿里云通义千问Qwen3系列模型存在专属参数约束:非流式请求必须关闭思考模式(enable_thinking=false),同时原生流式响应存在chunked编码异常。笔者通过Python代理服务统一封装:
from flask import Flask, request, Response
import requests
import json
app = Flask(__name__)
THIRD_PARTY_BASE_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1"
THIRD_PARTY_API_KEY = "sk-你的阿里云百炼真实APIKey"
@app.route("/v1/<path:path>", methods=["GET", "POST", "PUT", "DELETE"])
def proxy(path):
target_url = f"{THIRD_PARTY_BASE_URL}/{path}"
headers = {key: value for key, value in request.headers.items()
if key.lower() not in ["host", "authorization", "content-length"]}
headers["Authorization"] = f"Bearer {THIRD_PARTY_API_KEY}"
# 核心:自动处理 enable_thinking 参数
body = request.get_data()
if request.method in ["POST", "PUT"] and body:
try:
body_json = json.loads(body)
# 非流式且未显式设置时,自动关闭思考模式
if not body_json.get("stream", False) and "enable_thinking" not in body_json:
body_json["enable_thinking"] = False
body = json.dumps(body_json).encode("utf-8")
headers["Content-Length"] = str(len(body))
except json.JSONDecodeError:
pass
resp = requests.request(
method=request.method,
url=target_url,
headers=headers,
data=body,
stream=True
)
# 过滤冲突响应头,流式透传
excluded_headers = ['content-encoding', 'content-length', 'transfer-encoding', 'connection']
resp_headers = [(k, v) for k, v in resp.headers.items() if k.lower() not in excluded_headers]
def stream_generator():
for chunk in resp.iter_content(chunk_size=1024):
if chunk:
yield chunk
return Response(
stream_generator(),
status=resp.status_code,
headers=dict(resp_headers),
direct_passthrough=True
)
if __name__ == "__main__":
app.run(host="0.0.0.0", port=18001, debug=False, threaded=True)
4.2 OpenResty完整核心配置
配置基于OpenResty 1.31.1.1,包含共享内存计数、动态路由、流式透传、实时监控、日志统计全能力,可直接生产落地:
pid /tmp/openresty_test.pid;
error_log /tmp/openresty_error.log notice;
worker_processes auto;
events {
worker_connections 1024;
}
http {
log_format main '$remote_addr [$time_local] "$request" $status '
'上游: $upstream_addr 当前并发: $conn_total';
access_log /tmp/openresty_access.log main;
# 跨进程共享内存:全局并发计数器(多进程计数精准不冲突)
lua_shared_dict active_conns 1m;
# 主上游:本地大模型服务
upstream main_service {
server 10.10.1.xxx:18001 max_fails=3 fail_timeout=30s;
keepalive 32;
}
# 兜底上游:封装后的Qwen三方服务
upstream fallback_service {
server 10.10.1.xxx:18002 max_fails=3 fail_timeout=30s;
keepalive 32;
}
server {
listen 13008;
client_max_body_size 100M;
set $backend "";
set $conn_total 0;
# Lua核心:请求接入阶段判断并发、动态选路
access_by_lua_block {
local dict = ngx.shared.active_conns
-- 本地服务最大安全并发阈值
local MAX_MAIN_CONCURRENCY = 10
-- 原子+1,杜绝多进程计数偏差
local current = dict:incr("total", 1, 0)
ngx.var.conn_total = current
-- 核心分流逻辑
if current <= MAX_MAIN_CONCURRENCY then
ngx.var.backend = "http://main_service"
else
ngx.var.backend = "http://fallback_service"
end
}
# Lua核心:请求结束强制回收计数(成功/失败/超时均执行)
log_by_lua_block {
local dict = ngx.shared.active_conns
dict:incr("total", -1, 0)
}
# 统一转发配置,兼容大模型流式响应
location / {
proxy_pass $backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
# 关闭缓冲,解决流式chunked编码异常
proxy_buffering off;
proxy_cache off;
proxy_request_buffering off;
# 大模型长超时适配
proxy_connect_timeout 5s;
proxy_read_timeout 120s;
proxy_send_timeout 120s;
}
# 实时并发监控接口
location /status {
allow 127.0.0.1;
allow 10.10.1.0/24;
deny all;
default_type text/plain;
content_by_lua_block {
local dict = ngx.shared.active_conns
local num = dict:get("total") or 0
ngx.say("=== 大模型并发分流状态 ===")
ngx.say("当前活跃连接数: ", num)
ngx.say("本地服务并发上限: 30")
ngx.say("主服务地址: 10.10.1.xxx:18001")
ngx.say("兜底服务地址: 10.10.1.xxx:18002")
}
}
}
}
4.3 核心原理详解
- 共享内存计数:
lua_shared_dict实现多Worker进程内存共享,配合incr原子操作,彻底解决并发计数不准问题 - 双阶段Lua执行:
access_by_lua_block接入判路,log_by_lua_block收尾回收计数,100%避免计数泄露 - 流式专属优化:关闭代理缓冲,原生透传流式数据,彻底解决大模型对话的chunked编码报错
4.4 启动 & 重载命令
# 1. 检查配置语法
openresty -t -c /你的配置文件路径/openresty.conf
# 2. 启动服务
openresty -c /你的配置文件路径/openresty.conf
# 3. 修改配置后平滑重载
openresty -c /你的配置文件路径/openresty.conf -s reload
# 4. 停止服务
openresty -c /你的配置文件路径/openresty.conf -s stop
五、压力测试全流程验证
本次采用 siege 压测工具,模拟真实持续并发流量,分阶段验证分流逻辑有效性,贴合生产流量场景。
5.1 压测准备
编写POST请求配置文件,使用复杂Prompt拉长推理耗时,保证并发请求可堆叠,精准触发分流逻辑:
http://127.0.0.1:13008/v1/chat/completions POST {"model":"qwen3-8b","messages":[{"role":"user","content":"你是谁?"}],"stream":false}
5.2 分阶段测试验证
阶段1:小阈值逻辑校验(快速排错)
临时将并发阈值改为5,7并发压测,验证基础分流逻辑:
siege -f siege_urls.txt -H "Content-Type: application/json" -c 7 -r 1 -b
预期结果:最大5并发走本地服务,超额请求自动切换三方服务,无5xx报错。
阶段2:生产阈值压测
恢复阈值10,50并发持续压测60秒,模拟生产突发流量:
> /tmp/openresty_access.log
siege -f siege_urls.txt -H "Content-Type: application/json" -c 50 -t 60s -b
5.3 结果校验指标
-
并发上限保护:实时监控接口显示活跃连接数峰值稳定30,不超限
-
自动降级生效:日志统计18002服务存在稳定请求量
-
服务稳定性:压测全程无失败请求、无推理超时、无服务宕机
日志统计命令:
echo "本地服务请求数:" && grep "18001" /tmp/openresty_access.log | wc -l
echo "三方兜底请求数:" && grep "18002" /tmp/openresty_access.log | wc -l
六、方案优势与生产价值
-
零业务侵入:纯网关层实现,无需修改任何模型服务、前端业务代码
-
精准流量管控:原子级并发统计,严格保护本地GPU算力,杜绝超负载宕机
-
高可用容灾:突发高并发自动兜底,保证业务7*24小时可用
-
成本最优:低并发走免费本地算力,高并发按需调用付费三方API,平衡成本与稳定性
-
可观测性强:自带实时并发监控、精细化分流日志,便于运维统计与问题排查
七、总结与拓展
本文基于OpenResty+Lua实现了AI大模型服务精准并发限流+超量自动降级的完整落地方案,彻底解决了原生Nginx流量调度不精准、降级延迟的痛点。通过统一三方API接口封装,实现了双服务无缝切换,兼顾了服务稳定性、业务成本与用户体验。
2628

被折叠的 条评论
为什么被折叠?



