前言

大模型的问答一般是流式响应,本质上通过长连接的方式,服务端不断向客户端响应内容。如果是通过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次。
流式响应.png

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的情况下,达到配置的时间,不管连接是否存在,都会进行关闭。