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

如何配置FastAPI+Uvicorn微服务避免互相调用时冻结崩溃?

微服务循环调用冻结问题的解决方法

一、修复当前同步调用的阻塞问题

1. 给requests强制添加超时参数

同步的requests如果不设置超时,遇到网络异常或对方服务无响应时会一直阻塞线程/进程,导致Uvicorn worker被占满、服务冻结。必须显式设置超时,并捕获异常:

import requests
from fastapi import JSONResponse
import logging

logger = logging.getLogger(__name__)

def call_service2(data):
    try:
        # 分别设置连接超时(3秒)和读取超时(10秒),可根据业务调整
        response = requests.post("http://service2/api", json=data, timeout=(3, 10))
        response.raise_for_status()  # 主动抛出HTTP错误状态码异常
        return response.json()
    except requests.exceptions.RequestException as e:
        logger.error(f"调用service2失败: {str(e)}")
        return JSONResponse(status_code=503, content={"detail": "服务暂时不可用"})

2. 优化Uvicorn运行配置

Uvicorn默认配置无法有效应对阻塞场景,调整以下参数:

  • 启用多worker模式:避免单个worker被阻塞后整个服务无响应,启动命令添加--workers 4(建议值为CPU核数*2+1)
  • 设置连接超时:--timeout-keep-alive 60,避免无效长连接占用资源
  • 优雅关闭超时:--timeout-graceful-shutdown 30,给worker留足时间处理完现有请求再关闭
  • 若使用单worker异步模式,替换requests为异步HTTP客户端(如httpx.AsyncClient),避免阻塞事件循环:
from httpx import AsyncClient
from fastapi import JSONResponse
import logging

logger = logging.getLogger(__name__)

@app.get("/async-call")
async def async_call_service2(data):
    async with AsyncClient() as client:
        try:
            response = await client.post("http://service2/api", json=data, timeout=10.0)
            response.raise_for_status()
            return response.json()
        except Exception as e:
            logger.error(f"异步调用service2失败: {str(e)}")
            return JSONResponse(status_code=503, content={"detail": "服务暂时不可用"})

3. 配置Kubernetes健康探针

添加livenessProbe和readinessProbe,让K8s及时发现异常Pod并重启,同时避免将流量导向不健康的服务:

livenessProbe:
  httpGet:
    path: /health
    port: 8000
  initialDelaySeconds: 10
  periodSeconds: 5
  failureThreshold: 3
readinessProbe:
  httpGet:
    path: /health
    port: 8000
  initialDelaySeconds: 5
  periodSeconds: 3
  failureThreshold: 2

FastAPI需提供对应的健康检查接口:

from fastapi import FastAPI

app = FastAPI()

@app.get("/health")
async def health_check():
    return {"status": "healthy"}

二、架构层面优化:避免同步循环调用

当前的同步双向调用天然存在死锁风险(双方互相等待响应),更可靠的方案是改用异步消息队列(如RabbitMQ、Redis队列):

  • service1不再直接调用service2接口,而是将请求数据发送到消息队列
  • service2监听队列,收到消息后异步处理,完成后将结果发送到另一个结果队列
  • service1监听结果队列,获取处理结果后返回给前端

这种模式的优势:

  • 彻底规避同步阻塞和循环调用死锁
  • 自带重试、消息持久化机制,网络异常时不会丢失请求
  • 支持削峰填谷,流量突增时队列可缓冲请求,避免服务被压垮

三、额外建议

  • 完善日志:在请求发起、响应接收、异常捕获节点添加详细日志,包含请求ID、参数、耗时等信息,便于排查问题
  • 限流降级:用slowapi等工具给接口添加限流规则,调用失败时返回降级响应,避免请求长期阻塞
  • 链路追踪:引入链路追踪工具(如Jaeger),清晰查看请求在服务间的流转路径,快速定位阻塞点

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.02 13:13:11