You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flask应用部署Kubernetes后数据库连接丢失无法重连问题排查

问题分析与解决方案

你的核心问题在于全局数据库连接的更新逻辑错误,以及缺乏可靠的连接失效处理机制:

  1. 全局变量conn在except块中被重新赋值时,你没有声明使用全局变量,导致新创建的连接只是局部变量,后续请求依然使用原来的失效连接。
  2. 现有错误处理仅尝试一次重连,且未处理重连失败的情况,也无法覆盖连接在两次请求之间失效的场景。

解决方案一:修复全局连接的重连逻辑

如果坚持使用全局连接,需要明确更新全局变量,并增加二次错误捕获:

@app.route("/api/data/")
def api_data():
    global conn  # 声明使用全局变量
    try:
        df = get_data()
        return df.to_dict('records')
    except Exception as e:
        # 尝试重连并更新全局连接
        try:
            conn = pyodbc.connect(db_connection_string)
            df = get_data()
            return df.to_dict('records')
        except Exception as re_conn_err:
            return jsonify({"error": f"数据库连接失败: {str(re_conn_err)}"}), 500

但这种方式仍有缺陷:如果连接在两次请求之间失效,下一次请求还是会先触发错误再重连,用户体验不佳。


解决方案二:每次请求创建新连接(低并发场景首选)

直接在每次请求时创建新连接,用完自动关闭,彻底避免连接失效问题,实现简单可靠:

def get_data():
    # 使用上下文管理器自动管理连接生命周期
    with pyodbc.connect(db_connection_string) as conn:
        df = pd.read_sql('SELECT * FROM registry.data', conn)
        df = df.sort_values(by=["name"])
        df["id"] = range(1, len(df) + 1)
        return df

@app.route("/api/data/")
def api_data():
    try:
        df = get_data()
        return df.to_dict('records')
    except Exception as e:
        return jsonify({"error": f"获取数据失败: {str(e)}"}), 500

注意:这种方式在高并发场景下可能会创建过多数据库连接,需要确保数据库配置的最大连接数足够。


解决方案三:使用连接池(高并发场景最优)

借助SQLAlchemy实现连接池管理,它会自动处理连接的复用、失效重连,平衡性能与资源占用:

  1. 先安装依赖:
pip install sqlalchemy
  1. 修改代码:
from sqlalchemy import create_engine

# 创建带连接池的引擎
db_url = (
    f"mssql+pyodbc://{os.getenv('SERVER_ADMIN_LOGIN')}:"
    f"{os.getenv('PASSWORD')}@{os.getenv('SERVER_NAME')}/"
    f"{os.getenv('DB_NAME')}?driver=ODBC+Driver+18+for+SQL+Server"
)
# 配置连接池参数:pool_size为常驻连接数,max_overflow为临时扩展连接数
engine = create_engine(db_url, pool_size=5, max_overflow=10)

def get_data():
    with engine.connect() as conn:
        df = pd.read_sql('SELECT * FROM registry.data', conn)
        df = df.sort_values(by=["name"])
        df["id"] = range(1, len(df) + 1)
        return df

@app.route("/api/data/")
def api_data():
    try:
        df = get_data()
        return df.to_dict('records')
    except Exception as e:
        return jsonify({"error": f"获取数据失败: {str(e)}"}), 500

连接池会自动维护可用连接,当连接失效时会自动重建,无需手动处理重连逻辑,是高并发场景下的最优选择。


内容的提问来源于stack exchange,提问作者MKorona

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.09 23:37:40