Sanic+Tortoise-ORM中CancelledError致进程崩溃问题求助
解决Sanic+Tortoise-ORM查询超时引发的CancelledError进程崩溃问题
1. 优先解决查询慢的根源:添加数据库索引
你的查询超时本质是id_nunmber和deleted字段无索引,导致全表扫描。直接给这两个字段加联合索引:
CREATE INDEX idx_students_idnumber_deleted ON students (id_nunmber, deleted);
同时在Tortoise-ORM的Students模型里显式声明索引(确保ORM和数据库结构同步):
class Students(models.Model): id_nunmber = models.CharField(max_length=64) deleted = models.BooleanField(default=False) # 其他字段... class Meta: indexes = [ models.Index(fields=["id_nunmber", "deleted"]) ]
2. 捕获CancelledError,阻止异常蔓延导致进程崩溃
在查询代码外层添加异常捕获,处理asyncio.CancelledError,同时返回合理的业务错误:
import asyncio from sanic.exceptions import HTTPException # 在你的check_applyexam_data方法中修改 try: student: Students = await Students.filter(id_nunmber=data.id_nunmber, deleted=False).first() except asyncio.CancelledError: # 记录日志,抛出业务级超时异常 logger.error("查询学生信息超时") raise HTTPException(status_code=504, detail="服务超时,请稍后重试")
也可以通过Sanic全局异常处理器统一拦截这类异常,避免单个请求的异常拖垮进程:
from sanic import Sanic from sanic.response import json app = Sanic("my_app") @app.exception(asyncio.CancelledError) async def handle_cancelled_error(request, exception): logger.error(f"请求超时被取消: {request.path}") return json({"error": "服务超时"}, status=504)
3. 配置Tortoise-ORM的连接超时与连接池参数
调整Tortoise的数据库配置,设置合理的连接超时、查询超时,以及连接池存活检测,避免使用已中断的连接:
TORTOISE_ORM = { "connections": { "default": { "engine": "tortoise.backends.mysql", "credentials": { "host": "your_db_host", "port": 3306, "user": "your_user", "password": "your_pass", "database": "your_db", # 连接超时时间(秒) "connect_timeout": 10, # 单个查询超时时间(秒) "query_timeout": 5, # 连接池配置 "minsize": 5, "maxsize": 20, # 自动回收超过1小时的连接,防止数据库主动断开 "pool_recycle": 3600, # 获取连接前自动ping数据库,验证连接有效性 "pool_pre_ping": True } } }, "apps": { "models": { "models": ["your_app.models"], "default_connection": "default", } } }
4. 调整Sanic的请求超时设置
Sanic默认的请求超时可能过短,导致查询未完成就被强制取消。在Sanic配置中调整:
app.config.RESPONSE_TIMEOUT = 10 # 单位:秒,根据业务需求调整 app.config.KEEP_ALIVE_TIMEOUT = 75
内容的提问来源于stack exchange,提问作者yodew
相关产品推荐
相关产品推荐

