Flask+FastAPI+PostgreSQL插入优化:实现200QPS及连接错误排查
问题排查与性能优化方案
一、错误排查:socket.gaierror 连接失败错误
该错误为数据库连接时的域名解析/创建失败,结合日志与代码,原因及修复方案如下:
- 数据库连接参数异常
检查FastAPI中Database.create_pool方法的host变量是否正确赋值,确保其为PostgreSQL实际监听的地址(如127.0.0.1、localhost),避免空值、拼写错误或无法解析的主机名。 - 连接池配置过载
当前代码设置max_size=1000,远超过PostgreSQL默认max_connections(通常为100),导致请求过载时无法创建新连接。建议将max_size调整为不超过数据库最大连接数(如50,具体匹配PostgreSQL配置)。 - 连接超时未处理
当连接池耗尽时,获取连接的等待超时会引发异常,建议添加超时捕获:import asyncio from fastapi import HTTPException try: connection = await asyncio.wait_for(db.pool.acquire(), timeout=5) except asyncio.TimeoutError: raise HTTPException(status_code=503, detail="数据库连接池繁忙")
二、性能优化:实现200QPS插入目标
当前QPS仅16.17,需从全链路(Flask→FastAPI→PostgreSQL)针对性优化:
1. Flask层优化
- 替换同步请求为异步客户端
现有requests.post为同步阻塞调用,会限制gevent协程的并发能力,改用aiohttp异步客户端:
同时将Flask视图改为异步函数,使用支持异步的gunicorn worker:import aiohttp import asyncio async def write_sql(url, data): try: headers = {'Content-Type': 'application/json'} async with aiohttp.ClientSession() as session: async with session.post(url, json=data, headers=headers) as resp: return await resp.text() except Exception as e: logging.error(e)gunicorn --worker-class uvicorn.workers.UvicornWorker --workers 5 --threads 4 --bind 0.0.0.0:5000 main_api:app - 调整gunicorn配置
worker数量建议设为CPU核心数*2+1,线程数无需过高(协程模式下,线程数匹配CPU核心数即可,避免上下文切换开销)。
2. FastAPI层优化
- 移除Pandas数据转换开销
Pandas的DataFrame创建与转换是性能瓶颈,直接从JSON生成插入所需元组:@app.post('/api') async def insert_db(request: Request): data = await request.json() columns = data[0].keys() tuples = [tuple(item.values()) for item in data] async with db.pool.acquire() as connection: await connection.copy_records_to_table( table, schema_name=schema, records=tuples, columns=list(columns), timeout=10 ) return {"status": "success"} - 异步队列解耦插入逻辑
用Redis做异步队列,Flask直接将数据推送到队列,FastAPI后台批量消费插入,避免同步等待:- Flask端:将数据推送到Redis列表
- FastAPI端:启动后台任务,批量拉取队列数据执行插入
- 连接池自动管理
使用async with语法自动释放连接,避免连接泄漏。
3. PostgreSQL数据库优化
- 调整核心参数
修改postgresql.conf提升写入性能:max_connections = 200 # 匹配连接池max_size shared_buffers = 1GB # 建议为服务器内存的1/4 work_mem = 64MB # 提升排序、哈希操作效率 wal_buffers = 16MB # 扩大预写日志缓冲区 checkpoint_completion_target = 0.9 # 降低检查点开销 synchronous_commit = off # 关闭同步提交(需容忍少量数据丢失风险) - 批量插入优化
确保每次请求携带批量数据(如一次100条),最大化copy_records_to_table的批量写入效率,减少请求次数。 - 临时禁用索引
大量插入前禁用表索引,插入完成后重建,避免每次插入更新索引的开销。
4. 架构简化(可选)
直接用FastAPI替代Flask,移除中间层HTTP请求开销,将Flask业务逻辑迁移至FastAPI,流程简化为客户端→FastAPI→PostgreSQL。
内容的提问来源于stack exchange,提问作者Dmitry
相关产品推荐
相关产品推荐

