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

使用Gunicorn(含Worker)部署FastAPI服务器的数据更新异常问题

问题:FastAPI接口刷新后有时无法获取最新数据

我用FastAPI完成了一个简单的后端测试:通过Docs页面的POST接口提交数据,再通过GET接口读取数据。但每次按下F5刷新时,有时能获取到更新后的数据,有时却无法获取到最新数据。相关代码文件如下:

db_class.py

from sqlalchemy import Column, TEXT, INT, BIGINT
from sqlalchemy.orm import declarative_base

Base = declarative_base()

class Test(Base):
    __tablename__ = 'test'
    id = Column(BIGINT,nullable=False, autoincrement=True, primary_key=True)
    name = Column(TEXT, nullable=False)
    number = Column(INT, nullable=False)

db_conn.py

from sqlalchemy import *
from sqlalchemy.orm import sessionmaker

conn_string = "mysql+pymysql://root:password@mariadb:3306/example"

class engineconn:

    def __init__(self):
        self.engine = create_engine(conn_string, pool_recycle =500)

    def sessionmaker(self):
        Session = sessionmaker(bind=self.engine)
        session = Session()
        return session

    def connection(self):
        conn = self.engine.connect()
        return conn

main.py

from fastapi import FastAPI
from pydantic import BaseModel
from db_conn import engineconn
from db_class import Test

app = FastAPI()

engine = engineconn()
session = engine.sessionmaker()


class Item(BaseModel):
    name: str
    number: int


@app.get("/")
async def first_get():
    example = session.query(Test).all()
    return example


@app.post("/post")
async def first_post(item: Item):
    addMemo = Test(name=item.name, number=item.number)
    session.add(addMemo)
    session.commit()
    return item

Dockerfile

FROM python:3.9.0

WORKDIR /home/

RUN echo '2323'

RUN git clone (my git)

WORKDIR /home/(my_folder)

RUN pip install -r requirements.txt

EXPOSE 8080

CMD ["bash", "-c", "gunicorn main:app --worker-class=uvicorn.workers.UvicornWorker --workers=3 --bind 0.0.0.0:8080"]

docker-compose.yml

version: "3.7"
services:
  nginx:
    image: nginx:1.19.5
    networks:
      - network
    volumes:
      - /home/fastapi_chk/nginx.conf:/etc/nginx/nginx.conf
    ports:
      - 80:80
  fastapi_test:
    image: fastapi_test
    networks:
      - network
  mariadb:
    image: mariadb:10.5
    networks:
      - network
    volumes:
      - mariadb-database:/var/lib/mysql
    environment:
      MYSQL_ROOT_PASSWORD: rkwkrh13!#
    ports:
      - 3306:3306

networks:
  network:

volumes:
  mariadb-database:

问题原因分析

  • 全局会话复用问题:main.py中全局创建了一个session对象,所有请求共用同一个数据库会话。SQLAlchemy的会话会缓存查询结果,后续GET请求会优先读取缓存,不会实时从数据库拉取最新数据。
  • 多Worker进程冲突:Dockerfile中配置了3个gunicorn Worker进程,每个Worker都会初始化独立的全局session。当请求被分配到不同Worker时,部分Worker的会话缓存仍是旧数据,导致读取不到最新内容。
  • 会话生命周期管理错误:全局会话长期存在,未在请求结束后关闭或刷新,缓存无法及时更新。

解决方案

1. 为每个请求创建独立数据库会话

使用FastAPI的依赖注入机制,为每个请求分配独立的数据库会话,请求结束后自动关闭。修改main.py如下:

from fastapi import FastAPI, Depends
from pydantic import BaseModel
from sqlalchemy.orm import Session
from db_conn import engineconn
from db_class import Test

app = FastAPI()

engine = engineconn()

# 依赖函数:为每个请求创建新会话,请求结束后自动关闭
def get_db():
    db = engine.sessionmaker()
    try:
        yield db
    finally:
        db.close()

class Item(BaseModel):
    name: str
    number: int

@app.get("/")
async def first_get(db: Session = Depends(get_db)):
    # 使用请求级别的会话查询,避免缓存
    example = db.query(Test).all()
    return example

@app.post("/post")
async def first_post(item: Item, db: Session = Depends(get_db)):
    addMemo = Test(name=item.name, number=item.number)
    db.add(addMemo)
    db.commit()
    db.refresh(addMemo)  # 可选:返回包含数据库自动生成字段的最新对象
    return item

2. 验证效果

修改后,每个请求都会获取全新的数据库会话,查询时直接从数据库读取最新数据,彻底解决缓存导致的不一致问题。即使多Worker进程运行,每个请求的会话都是独立的,不会出现数据不同步的情况。


内容的提问来源于stack exchange,提问作者Chang yong Park

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 13:06:25