perf(全链路): 连接池/事务边界/轮询与 IO 效率收口
Java: - LLM 180s 读超时不再被全局 call-timeout 静默截断成 90s(长思考请求被掐断→重试→付费网关二次计费) - 代理 HttpClient 缓存改有界 LRU(jikip 每次提取新 IP,无界缓存持续泄漏 selector 线程与连接池) - 12 个 service 的 Redis 任务锁移出 @Transactional(自旋最坏 10s 白占 DB 连接,池仅 30),远端对象删/传改 afterCommit - 结果文件 Job 闸门拒绝时不再回退内联执行(改重新入队,避免把背压转嫁给 MQ 消费线程) - imagevideo 每秒扫描加列投影、过期清理加 LIMIT;权限页整表查询改列投影(不再拉回密码哈希) - 哈希改 HexFormat;补 5 处"不能改"的技术依据注释(批量插入会丢回填主键、流式丢模板与图片等) 前端:4 个工具页轮询改轻量端点(带 fallback);PriceTrack 快照节流写盘;候选店铺表分页;页面隐藏时停表 客户端:HTTP 连接池按出口复用(Session 仍每请求新建,保持无跨请求状态);品牌检测 WIPO 逐请求握手; 代理配置按 mtime 缓存;串行任务改专属池;异常降级为标签页重连;紫鸟启动改端口轮询;模板编译缓存; 日志上报连接与落盘收口;Flask 版本 API 改按请求复用连接
This commit is contained in:
+4
-1
@@ -11,7 +11,7 @@ import secrets
|
||||
from flask import Flask
|
||||
from flask_cors import CORS
|
||||
|
||||
from utils.db import init_db
|
||||
from utils.db import close_db, init_db
|
||||
from blueprints.version import version_bp
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
|
||||
@@ -36,6 +36,9 @@ app.secret_key = os.environ.get('SECRET_KEY', secrets.token_hex(32))
|
||||
# 注册蓝图:仅版本公开 API(管理后台 API 已迁 Java,见模块 docstring)
|
||||
app.register_blueprint(version_bp)
|
||||
|
||||
# 请求级数据库连接随请求结束释放(utils/db.get_db 复用同一连接)
|
||||
app.teardown_appcontext(close_db)
|
||||
|
||||
|
||||
def run_app(host='0.0.0.0', port=15124):
|
||||
init_db()
|
||||
|
||||
+85
-1
@@ -1,9 +1,26 @@
|
||||
"""
|
||||
数据库连接与初始化
|
||||
|
||||
请求级连接复用:pymysql 每次 connect 都要做一次完整的鉴权握手,而本进程
|
||||
(15124)只服务 /api/version、/api/version/latest 这类轻量查询,握手开销
|
||||
占了单次请求的大头。连接因此挂在 flask.g 上按请求复用,请求结束由
|
||||
close_db(注册在 app.teardown_appcontext)统一释放。
|
||||
"""
|
||||
import re
|
||||
|
||||
import pymysql
|
||||
|
||||
try:
|
||||
from flask import g, has_app_context
|
||||
except ImportError: # 非 Flask 环境(脚本/离线核查)下退化为每次新建连接
|
||||
g = None
|
||||
|
||||
def has_app_context() -> bool:
|
||||
return False
|
||||
|
||||
# 请求级连接挂在 flask.g 上的属性名(避免与业务字段冲突)
|
||||
_CONN_ATTR = "_shufu_db_conn"
|
||||
|
||||
try:
|
||||
from config import mysql_host as config_mysql_host
|
||||
from config import mysql_user as config_mysql_user
|
||||
@@ -44,7 +61,7 @@ def describe_db_target():
|
||||
)
|
||||
|
||||
|
||||
def get_db():
|
||||
def _connect():
|
||||
return pymysql.connect(
|
||||
host=mysql_host,
|
||||
user=mysql_user,
|
||||
@@ -55,6 +72,73 @@ def get_db():
|
||||
)
|
||||
|
||||
|
||||
def _is_alive(conn) -> bool:
|
||||
"""连接可用性探测:已关闭直接判死,否则发一次 COM_PING。
|
||||
|
||||
COM_PING 一次往返远小于一次完整鉴权握手;不用 ping(reconnect=True)
|
||||
(该参数在新版 pymysql 已废弃,且失败时会自行重连、语义不可控)。
|
||||
"""
|
||||
try:
|
||||
if not conn.open:
|
||||
return False
|
||||
conn.ping(reconnect=False)
|
||||
return True
|
||||
except Exception:
|
||||
return False
|
||||
|
||||
|
||||
def _close_quietly(conn) -> None:
|
||||
"""静默关闭连接(可能为 None / 已关闭 / 断连)。"""
|
||||
if conn is None:
|
||||
return
|
||||
try:
|
||||
conn.close()
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
|
||||
def get_db():
|
||||
"""取当前请求的数据库连接(同一请求内复用,避免每次请求都做鉴权握手)。
|
||||
|
||||
连接挂在 flask.g 上,请求结束由 close_db 释放;被服务端 wait_timeout
|
||||
断开、或调用方提前 close 过,这里都会静默换成新连接,调用方无感知。
|
||||
无 Flask 应用上下文时(脚本调用)退回每次新建,保持旧行为。
|
||||
"""
|
||||
ctx = g if has_app_context() else None
|
||||
conn = getattr(ctx, _CONN_ATTR, None) if ctx is not None else None
|
||||
if conn is not None:
|
||||
if _is_alive(conn):
|
||||
return conn
|
||||
# 断连/已被关闭:丢弃旧连接后重建(不把坏连接交给业务查询)
|
||||
_close_quietly(conn)
|
||||
try:
|
||||
delattr(ctx, _CONN_ATTR)
|
||||
except Exception:
|
||||
pass
|
||||
conn = _connect()
|
||||
if ctx is not None:
|
||||
setattr(ctx, _CONN_ATTR, conn)
|
||||
return conn
|
||||
|
||||
|
||||
def close_db(exc=None) -> None:
|
||||
"""释放当前请求的连接(注册为 app.teardown_appcontext 回调)。
|
||||
|
||||
异常路径同样会走 teardown,因此查询抛错时连接不会泄漏到下一次请求。
|
||||
"""
|
||||
ctx = g if has_app_context() else None
|
||||
if ctx is None:
|
||||
return
|
||||
conn = getattr(ctx, _CONN_ATTR, None)
|
||||
if conn is None:
|
||||
return
|
||||
try:
|
||||
delattr(ctx, _CONN_ATTR)
|
||||
except Exception:
|
||||
pass
|
||||
_close_quietly(conn)
|
||||
|
||||
|
||||
def init_db():
|
||||
"""确保版本公开 API 依赖的最小表结构存在。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user