11#!/usr/bin/env python3
22"""
33生产环境启动脚本
4- 支持高并发部署
54"""
65
76import os
87import sys
98import socket
9+ import signal
10+ import uvicorn
1011from pathlib import Path
1112
1213# 添加项目根目录到Python路径
@@ -33,10 +34,22 @@ def get_local_ip():
3334 return "127.0.0.1"
3435
3536
37+ def signal_handler (signum , frame ):
38+ """信号处理器"""
39+ logger .info (f"收到信号 { signum } ,正在优雅关闭服务..." )
40+ sys .exit (0 )
41+
42+
3643def main ():
3744 """主函数"""
45+ # 注册信号处理器
46+ signal .signal (signal .SIGINT , signal_handler )
47+ signal .signal (signal .SIGTERM , signal_handler )
48+
3849 try :
39- logger .info (f"生产环境服务启动中,监听地址: { settings .host } :{ settings .port } " )
50+ logger .info (
51+ f"生产环境服务启动中(Uvicorn),监听地址: { settings .host } :{ settings .port } "
52+ )
4053 print ("=" * 60 )
4154 local_ip = get_local_ip ()
4255 print (
@@ -45,46 +58,21 @@ def main():
4558 )
4659 print ("=" * 60 )
4760
48- # 使用gunicorn启动,支持高并发
49- import gunicorn .app .base
50-
51- class StandaloneApplication (gunicorn .app .base .BaseApplication ):
52- def __init__ (self , app , options = None ):
53- self .options = options or {}
54- self .application = app
55- super ().__init__ ()
56-
57- def load_config (self ):
58- config = {
59- key : value
60- for key , value in self .options .items ()
61- if key in self .cfg .settings and value is not None
62- }
63- for key , value in config .items ():
64- self .cfg .set (key .lower (), value )
65-
66- def load (self ):
67- return self .application
68-
69- options = {
70- "bind" : f"{ settings .host } :{ settings .port } " ,
71- "workers" : 1 , # 单进程模式,避免模型重复加载
72- "worker_class" : "uvicorn.workers.UvicornWorker" , # 使用UvicornWorker支持ASGI
73- "worker_connections" : 1000 , # 每个worker的连接数
74- "max_requests" : 1000 , # 每个worker处理的最大请求数
75- "max_requests_jitter" : 100 , # 随机抖动,避免同时重启
76- "timeout" : 120 , # 请求超时时间
77- "keepalive" : 2 , # keep-alive连接数
78- "preload_app" : True , # 预加载应用
79- "access_log_format" : '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s" %(D)s' ,
80- "accesslog" : "-" , # 访问日志输出到stdout
81- "errorlog" : "-" , # 错误日志输出到stderr
82- "loglevel" : "info" ,
83- }
84-
85- from app .application import app
86-
87- StandaloneApplication (app , options ).run ()
61+ # 使用Uvicorn启动,配置优化
62+ uvicorn .run (
63+ "app.application:app" ,
64+ host = settings .host ,
65+ port = settings .port ,
66+ reload = False , # 生产环境关闭热重载
67+ workers = 1 , # 单进程模式,避免模型重复加载
68+ access_log = True , # 开启访问日志
69+ log_level = "info" ,
70+ timeout_keep_alive = 30 , # keep-alive超时
71+ timeout_graceful_shutdown = 300 , # 优雅关闭超时
72+ limit_concurrency = 1000 , # 并发连接限制
73+ limit_max_requests = 1000 , # 最大请求数限制
74+ backlog = 2048 , # 连接队列大小
75+ )
8876
8977 except KeyboardInterrupt :
9078 logger .info ("收到中断信号,正在退出服务。" )
0 commit comments