推荐使用 后端服务 + Gunicorn + Supervisor + Nginx 选型组合来部署服务,各选型作用如下:
后端服务:使用 FastAPI 或 Flask 构建后端服务
多进程启动:使用 Gunicorn 启动后端服务
进程监管:使用 Supervisor 监管 Gunicorn 启动命令,进行持久化启动
反向代理与负载均衡:使用 Nginx 进行反向代理和负载均衡(控制并发)
(Step01)后端服务
使用 FastAPI 或 Flask 构建后端服务
# FastAPI 服务文件 /home/faramita/PythonWorks/my_item/App_Http_Server.py 示例内容如下:
import time
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.responses import JSONResponse
app = FastAPI()
# 配置 CORS
app.add_middleware(
CORSMiddleware, # noqa
allow_origins=["*"], # 允许所有源,生产环境应限制为具体域名
allow_credentials=True,
allow_methods=["*"], # 允许所有方法(如 GET、POST 等)
allow_headers=["*"], # 允许所有请求头
)
@app.post("/AIVoice/TTS/CosyVoice2/audio-generate")
async def audio_generate():
try:
# 模拟音频生成
time.sleep(5)
print("音频生成完成!")
result_data = {"code": "200", "message": "成功"}
return JSONResponse(content=result_data)
except Exception as e:
print("音频生成失败!")
result_data = {"code": "999", "message": "未知错误"}
return JSONResponse(content=result_data, status_code=400)
def init_model():
# 模拟模型加载
time.sleep(5)
print("模型加载完成!")
if __name__ == "__main__":
# 即时启动方式:python App_Http_Server.py
# 模型初始化
init_model()
import uvicorn
uvicorn.run(app, host='0.0.0.0', port=12321)
else:
# gunicorn 启动方式:当模块被导入时自动初始化模型
# 模型初始化
init_model()
(Step02)多进程启动
使用 Gunicorn 启动后端服务
# FastAPI 服务所在 conda 虚拟环境:/home/faramita/anaconda3/envs/my_item_py310
# 且该环境已安装 gunicorn
conda activate my_item_py310
gunicorn App_Http_Server:app --workers 1 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:12321 --timeout 300
# App_Http_Server:app : 需要启动的服务
# --workers 1: 启动 1 个并发服务
# --worker-class uvicorn.workers.UvicornWorker: 指定 ASGI 异步工作进程
# --bind 0.0.0.0:12321: 绑定地址和端口
# --timeout 300: 超时限制
# 上行命令仅为测试,如能成功运行,则表示多进程启动成功
# 然后即可终止命令,后续会使用 supervisor 监管启动
(Step03)进程监管
使用 Supervisor 监管 Gunicorn 启动命令,进行持久化启动
# Ubuntu 系统已安装 supervisor
# 新建 supervisor 子配置文件
# /etc/supervisor/conf.d/my_server.conf 配置文件内容示例如下:
[program:my_server]
directory=/home/faramita/PythonWorks/my_item
command=/home/faramita/anaconda3/envs/my_item_py310/bin/gunicorn App_Http_Server:app --workers 1 --worker-class uvicorn.workers.UvicornWorker --bind 0.0.0.0:12321 --timeout 300
stopsignal=TERM
stopwaitsecs=60
autostart=true
autorestart=true
startsecs=30
user=root
redirect_stderr=true
stdout_logfile=/home/faramita/PythonWorks/my_item/run.log
stdout_logfile_maxbytes=20MB
stdout_logfile_backups=50
stderr_logfile=/home/faramita/PythonWorks/my_item/run_error.log
stderr_logfile_maxbytes=20MB
stderr_logfile_backups=50
environment=CUDA_VISIBLE_DEVICES="0"
(Step04)反向代理与负载均衡
使用 Nginx 进行反向代理和负载均衡(控制并发)
# Ubuntu 系统已安装 nginx
# 配置文件 /home/faramita/nginx-xie/conf/nginx.conf 如下
# 实现效果:
# 服务器集群共 3 台 GPU 服务器
# 每台 GPU 服务器有 2 张 GPU 卡(如 RTX3090)
# 每张 GPU 卡都运行了一个服务(如声音克隆服务),url 如 http://192.168.1.10:12321/AIVoice/TTS/CosyVoice2/xxx
# 但由于 AI 服务比较耗显存,因此实际上一张卡只能支持 2 并发
# 所以需要限制:客户端在调用服务器集群服务时,每张卡只接受 2 个并发请求,每台服务器只接受 2×2=4 个并发请求,服务器集群只接受 3×4=12 个并发请求
# 最终 GPU 集群提供统一的服务访问 url ,如 http://www.jusdot.cn:9080/AIVoice/TTS/CosyVoice2/xxx
events {
# 增加连接数以支持更多并发
worker_connections 2048;
use epoll;
multi_accept on;
worker_rlimit_nofile 65535;
}
http {
# 设置传输文件大小
client_max_body_size 100M;
# 限制整个服务器集群的总并发连接数
limit_conn_zone $server_name zone=cluster_conn_limit:10m;
# (可选)限制单个客户端 IP 的并发连接数
limit_conn_zone $binary_remote_addr zone=client_conn_limit:10m;
# 定义服务器集群
upstream tts_cluster {
# 使用最少连接数负载均衡算法
least_conn;
# 服务器 01
server 192.168.1.10:12321 max_conns=2 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.10:12322 max_conns=2 weight=1 max_fails=3 fail_timeout=30s;
# 服务器 02
server 192.168.1.11:12321 max_conns=2 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.11:12322 max_conns=2 weight=1 max_fails=3 fail_timeout=30s;
# 服务器 03
server 192.168.1.12:12321 max_conns=2 weight=1 max_fails=3 fail_timeout=30s;
server 192.168.1.12:12322 max_conns=2 weight=1 max_fails=3 fail_timeout=30s;
# 保持连接活跃
keepalive 64;
}
# 定义日志格式(针对 TTS 集群优化)
log_format cluster '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for" '
'upstream_addr=$upstream_addr '
'upstream_response_time=$upstream_response_time '
'request_time=$request_time '
'server_name=$server_name '
'connections_active=$connections_active '
'upstream_status=$upstream_status '
'upstream_connect_time=$upstream_connect_time';
# 服务器配置
server {
# 监听容器内 9999 端口(nginx 部署时 docker-compose.yml 中设置了 '9080:9999')
listen 9999;
server_name 192.168.1.100;
# 访问日志
access_log /var/log/nginx/cosyvoice_cluster_access.log cluster;
error_log /var/log/nginx/cosyvoice_cluster_error.log;
# 超时设置(通用配置,适合大多数服务)
proxy_connect_timeout 30s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 缓冲区设置(通用配置,适合普通服务)
proxy_buffering on;
proxy_request_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# 代理路由
location /AIVoice/TTS/CosyVoice2/ {
# 限制整个服务器集群的总并发连接数(优先级最高),如:3台服务器 × 2张卡 × 2并发 = 12 总并发
limit_conn cluster_conn_limit 12;
# (可选)限制单个客户端 IP 的并发连接数
limit_conn client_conn_limit 6;
# 当超过并发连接限制时,返回 503 错误
limit_conn_status 503;
# 将请求转发给上游服务器集群
proxy_pass http://tts_cluster/AIVoice/TTS/CosyVoice2/;
# 设置代理头,确保后端服务能正确获取客户端信息
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
# HTTP/1.1 协议支持
proxy_http_version 1.1;
# 故障转移配置
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
proxy_next_upstream_tries 3;
proxy_next_upstream_timeout 30s;
# 流式 TTS 服务专用配置(覆盖 server 块的通用配置)
gzip off;
proxy_buffering off;
proxy_request_buffering off;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
}
# 集群状态监控端点
location /cluster/status {
access_log off;
add_header Content-Type application/json;
return 200 '{"status": "healthy", "cluster": "tts_cluster", "timestamp": "$time_iso8601", "total_capacity": 12, "servers": 3, "gpus_per_server": 2, "concurrent_per_gpu": 2}';
}
# 健康检查端点
location /health {
access_log off;
return 200 "healthy\n";
add_header Content-Type text/plain;
}
# 错误页面处理
error_page 502 503 504 @error_page;
location @error_page {
internal;
add_header Content-Type application/json always;
return 503 '{"error": {"code": "service_unavailable", "message": "超出并发限制,服务器过载,请稍后重试", "type": "cluster_overload", "timestamp": "$time_iso8601"}}';
}
# 默认错误处理
error_page 404 @not_found;
location @not_found {
internal;
add_header Content-Type application/json always;
return 404 '{"error": {"code": "not_found", "message": "请求的资源不存在", "type": "not_found", "timestamp": "$time_iso8601"}}';
}
}
}
评论区