
Ng热更新-流式响应不中断
前言
大模型的问答一般是流式响应,本质上通过长连接的方式,服务端不断向客户端响应内容。如果是通过nginx来进行负载均衡到不同的后面响应服务,那后端模型服务部署升级时,是否可以通过nginx的热更新调整负载均衡,同时保证正在处理的长连接不中断呢,本篇通过实验进行测试。
测试
测试步骤
1、首先需要配置nginx不启用内容缓存buffer,使得服务端的流式响应被直接输出
在 location 下配置
# 去掉内容缓存,支持sse流式响应立马返回
proxy_buffering off;
proxy_cache off;
完整location配置如下:
location /api/v1/ {
# try_files $uri $uri/ =404;
# 去掉内容缓存,支持sse流式响应立马返回
proxy_buffering off;
proxy_cache off;
proxy_set_header HOST $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://127.0.0.1:5001;
}
2、通过Python便携测试类,模拟大模型的流式响应
app.py
from flask import Flask
from controller.ai_api import ai_api_routes
app = Flask(__name__)
app.register_blueprint(ai_api_routes)
if __name__ == '__main__':
app.run(debug=True, port=5001)
3、在controller目录下创建ai_api.py
import time
from flask import Blueprint, Response
# 定义路由
ai_api_routes = Blueprint("ai_api_routes", __name__)
# 流式响应
@ai_api_routes.route('/api/v1/stream/<int:duration>')
def stream(duration):
def generate():
start_time = time.time()
while time.time() - start_time < duration:
current_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())
yield f"data: {current_time}\n\n"
time.sleep(1)
return Response(generate(), content_type='text/event-stream')
4、测试
4.1、浏览器访问:ip:port/api/v1/stream/30
流式响应,每秒输出一次当前时间,共计输出30次。
4.2、30秒(上面流式响应30秒)内修改nginx,并执行 nginx -s reload 进行热更新。
proxy_pass代理一个不存在的端口,随便写一个。
# proxy_pass http://127.0.0.1:5001;
proxy_pass http://127.0.0.1:50011;
4.3、观察浏览器的输出是否会中断
发现输出正常,当再次访问时便会报错。
关于 nginx -s reload
nginx -s reload 测试下来不影响长连接响应。
nginx -s reload 的生效时间取决于以下几个因素:
1、旧连接的关闭:nginx -s reload 会启动新的 worker 进程来处理新请求,但旧的 worker 进程会继续处理已建立的连接,直到这些连接关闭。如果存在长连接(如 Keep-Alive),旧的 worker 进程可能会持续运行,直到这些连接自然断开或达到 worker_shutdown_timeout 时间。
2、worker_shutdown_timeout 配置:在 Nginx 配置文件中,可以设置 worker_shutdown_timeout 参数,它定义了旧 worker 进程在关闭前等待的时间。如果未设置此参数,旧的 worker 进程会一直等待,直到所有连接关闭。
worker_shutdown_timeout配置在nginx.conf main段:
worker_shutdown_timeout 300s;
总结
在不配置worker_shutdown_timeout的情况下,nginx -s reload不会中断旧的worker进程的长连接,直到连接关闭,同时会启动新的worker来处理新的情况。
在配置了worker_shutdown_timeout的情况下,达到配置的时间,不管连接是否存在,都会进行关闭。