0.0.1
This commit is contained in:
152
app/main.py
Normal file
152
app/main.py
Normal file
@@ -0,0 +1,152 @@
|
||||
from fastapi import FastAPI
|
||||
from settings import TORTOISE_ORM
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
from tortoise.contrib.fastapi import register_tortoise
|
||||
from apscheduler.schedulers.asyncio import AsyncIOScheduler
|
||||
from apscheduler.triggers.interval import IntervalTrigger
|
||||
from tortoise import Tortoise
|
||||
from contextlib import asynccontextmanager
|
||||
from apis import app as main_router
|
||||
import asyncio
|
||||
import signal
|
||||
import sys
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
"""
|
||||
应用生命周期管理函数
|
||||
|
||||
- 启动:注册定时任务并启动调度器
|
||||
- 关闭:优雅关闭调度器与数据库连接
|
||||
"""
|
||||
print('项目启动...')
|
||||
|
||||
# 初始化数据库连接(使用 Tortoise 直接初始化,确保路由与定时任务可用)
|
||||
try:
|
||||
await Tortoise.init(config=TORTOISE_ORM)
|
||||
print('数据库初始化完成')
|
||||
except Exception as e:
|
||||
print(f'数据库初始化失败: {e}')
|
||||
|
||||
# 每30分钟保持一次数据库连接活跃
|
||||
scheduler.add_job(
|
||||
keep_db_connection_alive,
|
||||
IntervalTrigger(minutes=30),
|
||||
id='keep_db_alive',
|
||||
name='保持数据库连接',
|
||||
coalesce=True,
|
||||
misfire_grace_time=30,
|
||||
)
|
||||
|
||||
|
||||
scheduler.start()
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
print('项目结束...')
|
||||
|
||||
# 关闭数据库连接
|
||||
print('关闭数据库连接...')
|
||||
try:
|
||||
await asyncio.wait_for(Tortoise.close_connections(), timeout=2)
|
||||
except asyncio.TimeoutError:
|
||||
print('关闭数据库连接超时')
|
||||
except Exception as e:
|
||||
print(f'关闭数据库连接出错: {e}')
|
||||
|
||||
# 关闭调度器
|
||||
print('关闭调度器...')
|
||||
try:
|
||||
if scheduler is not None and hasattr(scheduler, 'shutdown'):
|
||||
scheduler.shutdown(wait=False)
|
||||
except Exception as e:
|
||||
print(f'关闭调度器出错: {e}')
|
||||
|
||||
|
||||
|
||||
# 创建 FastAPI 应用实例
|
||||
app = FastAPI(lifespan=lifespan)
|
||||
|
||||
# 配置 CORS 中间件
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["*"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
# 创建调度器实例
|
||||
scheduler = AsyncIOScheduler()
|
||||
|
||||
# 包含主路由
|
||||
app.include_router(main_router)
|
||||
|
||||
# 注意:使用自定义 lifespan 已在启动时手动初始化数据库。
|
||||
# 若改回默认事件机制,可重新启用 register_tortoise。
|
||||
|
||||
|
||||
async def keep_db_connection_alive():
|
||||
"""
|
||||
保持数据库连接活跃的函数
|
||||
定期执行简单查询以防止连接超时
|
||||
"""
|
||||
try:
|
||||
conn = Tortoise.get_connection("default")
|
||||
await conn.execute_query("SELECT 1")
|
||||
print("数据库连接检查成功")
|
||||
except Exception as e:
|
||||
print(f"数据库连接检查失败: {e}")
|
||||
|
||||
|
||||
def signal_handler():
|
||||
"""
|
||||
处理终止信号,确保资源正确释放
|
||||
"""
|
||||
|
||||
async def shutdown():
|
||||
print("收到终止信号,开始优雅关闭...")
|
||||
|
||||
# 关闭数据库连接
|
||||
print("关闭数据库连接...")
|
||||
try:
|
||||
await Tortoise.close_connections()
|
||||
except Exception as e:
|
||||
print(f"关闭数据库连接时出错: {e}")
|
||||
|
||||
# 关闭调度器
|
||||
print("关闭调度器...")
|
||||
try:
|
||||
scheduler.shutdown()
|
||||
except Exception as e:
|
||||
print(f"关闭调度器时出错: {e}")
|
||||
|
||||
print("所有资源已关闭,程序退出")
|
||||
sys.exit(0)
|
||||
|
||||
loop = asyncio.get_event_loop()
|
||||
loop.create_task(shutdown())
|
||||
# 给异步任务一些时间完成
|
||||
loop.run_until_complete(asyncio.sleep(2))
|
||||
sys.exit(0)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from uvicorn import run
|
||||
|
||||
# 注册信号处理
|
||||
for sig in (signal.SIGINT, signal.SIGTERM):
|
||||
signal.signal(sig, lambda sig, frame: signal_handler())
|
||||
|
||||
run(
|
||||
'main:app',
|
||||
host='0.0.0.0',
|
||||
port=6060,
|
||||
reload=False,
|
||||
workers=1,
|
||||
# loop='uvloop',
|
||||
http='httptools',
|
||||
limit_concurrency=10000,
|
||||
backlog=4096,
|
||||
timeout_keep_alive=5
|
||||
)
|
||||
Reference in New Issue
Block a user