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

FastAPI中自定义Middleware搭配StreamingResponse出现504网关超时问题

解决FastAPI自定义LoggingMiddleware搭配StreamingResponse导致Nginx 504超时问题

核心问题分析

自定义日志中间件大概率是破坏了StreamingResponse的流式传输特性:这类响应依赖分块编码(Transfer-Encoding: chunked)实时返回数据,若中间件试图缓存、读取完整响应体,或阻塞了响应流的传递,会导致Nginx长时间等待完整响应触发超时;而FileResponse是一次性返回完整文件内容,不会触发这类冲突。

具体修复方案

  • 跳过StreamingResponse的响应体读取
    很多日志中间件会强制读取完整响应体用于日志,但这会彻底阻塞流式传输。修改中间件,仅对非流式响应做体内容记录:

    async def dispatch(self, request: Request, call_next):
        response = await call_next(request)
        # 针对StreamingResponse仅记录响应类型,不读取body
        if isinstance(response, StreamingResponse):
            self.logger.info(f"Streaming response sent: {request.url.path}")
        else:
            # 非流式响应正常读取body日志
            body = await response.body()
            self.logger.info(f"Response body: {body.decode()}")
        return response
    
  • 保留StreamingResponse的原始响应头
    流式响应依赖Transfer-Encoding: chunked等特定头,若中间件随意修改或覆盖响应头,会导致Nginx无法识别流式传输。确保中间件仅对非流式响应做头修改:

    async def dispatch(self, request: Request, call_next):
        response = await call_next(request)
        if not isinstance(response, StreamingResponse):
            # 仅给非流式响应添加自定义头
            response.headers["X-Logged"] = "true"
        # 流式响应直接返回,不修改头
        return response
    
  • 移除中间件中的同步阻塞操作
    若日志中间件包含同步IO(如同步写入文件、耗时的日志格式化),会拖慢流式响应的发送速度。替换为异步日志操作:

    # 使用异步日志库示例(如structlog异步绑定器)
    import structlog
    from structlog.stdlib import AsyncBoundLogger
    
    logger: AsyncBoundLogger = structlog.get_logger()
    
    async def dispatch(self, request: Request, call_next):
        response = await call_next(request)
        # 异步记录日志,避免阻塞响应流
        await logger.ainfo(
            "request_processed",
            path=str(request.url),
            response_type=type(response).__name__
        )
        return response
    
  • 临时适配Nginx配置(辅助验证)
    若需快速验证中间件修复效果,可临时调整Nginx的超时设置,但核心仍需修复中间件逻辑:

    location / {
        proxy_pass http://your_fastapi_upstream;
        proxy_http_version 1.1;
        proxy_set_header Connection ""; # 适配长连接流式传输
        proxy_read_timeout 300s; # 适当延长超时窗口
    }
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.07 11:00:55