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

FastAPI跨服务高频互请求导致微服务冻结问题求助

双向互调FastAPI微服务高负载冻结问题解决思路

问题背景

用FastAPI搭建两个双向互调的微服务:服务A向服务B发起"How are you?"请求,B回复"Good!";反之服务B也会向A发起同样请求,请求按设定延迟循环执行。两个服务核心代码一致,仅启动配置不同。

服务核心代码

from fastapi import FastAPI
import requests
import uvicorn
import asyncio

app = FastAPI()

def get(url, headers, json_data=False):
    if json_data:
        r = requests.get(url, headers=headers, json=json_data)
    else:
        r = requests.get(url, headers=headers)
    return r

@app.get("/")
async def how_are_you():
    message = f"{service_name}: Good!"
    print(message)
    return message

async def toc_toc(message):
    await asyncio.sleep(5)
    url = f"http://{remote_host}:{remote_port}/"
    headers = {
        'accept': 'application/json',
    }
    count = 0
    while True:
        await asyncio.sleep(waiting)
        print(f"{count}\t{service_name}: {message}!")
        get(url, headers)
        count += 1

async def run_webserver():
    config = uvicorn.Config(app, host=host, port=port)
    server = uvicorn.Server(config)
    await server.serve()

async def main():
    await asyncio.gather(
        toc_toc("How are you"),
        run_webserver()
    )

服务1启动配置

if __name__ == "__main__":
    waiting = 0.1
    service_name = "service_1"
    host = "0.0.0.0"
    port = 82
    remote_host = "0.0.0.0"
    remote_port = 83
    loop = asyncio.get_event_loop()
    tasks = main()
    loop.run_until_complete(tasks)

服务2启动配置

if __name__ == "__main__":
    waiting = 0.1
    service_name = "service_2"
    host = "0.0.0.0"
    port = 83
    remote_host = "0.0.0.0"
    remote_port = 82
    loop = asyncio.get_event_loop()
    tasks = main()
    loop.run_until_complete(tasks)

问题现象

  • 当waiting延迟设为1秒时,服务运行正常;
  • 延迟降至0.1秒或更低时,双向互调数百次后服务无报错冻结;
  • 单向请求(仅一个服务发起请求)时,即使延迟设为0.001秒也能正常运行;
  • 问题在Mac M1本地环境和本地Kubernetes集群中均复现,需要支持0.001秒延迟以模拟生产负载峰值。

解决思路

1. 替换同步HTTP客户端为异步实现

问题根源:requests是同步阻塞库,在asyncio事件循环中调用会阻塞整个线程。双向高频率互调时,大量阻塞请求会占用事件循环的所有资源,导致服务无法处理新请求或自身的异步任务,最终冻结。

解决方案:改用httpx.AsyncClient,它支持异步请求,不会阻塞事件循环。修改请求函数为异步版本,并在调用时添加await关键字。

2. 限制并发请求数

问题根源:双向互调会形成请求闭环,高频率下请求量会指数级增长,超出服务的处理能力,导致资源耗尽。

解决方案:使用asyncio.Semaphore限制并发请求的最大数量,避免瞬间产生过多请求压垮服务。

3. 优化事件循环性能

问题根源:默认的asyncio事件循环在高负载下性能有限,尤其是ARM架构的Mac M1设备或K8s环境中,可能无法应对高频请求。

解决方案:使用uvloop作为事件循环,它是基于libuv的高性能asyncio事件循环实现,能显著提升高负载下的处理能力。

修改后的核心代码示例

from fastapi import FastAPI
import httpx
import uvicorn
import asyncio
from asyncio import Semaphore

app = FastAPI()
# 限制最大并发请求数,可根据实际情况调整
request_semaphore = Semaphore(100)

async def get(url, headers, json_data=False):
    async with request_semaphore:
        async with httpx.AsyncClient() as client:
            if json_data:
                response = await client.get(url, headers=headers, json=json_data)
            else:
                response = await client.get(url, headers=headers)
            return response

@app.get("/")
async def how_are_you():
    message = f"{service_name}: Good!"
    print(message)
    return message

async def toc_toc(message):
    await asyncio.sleep(5)
    url = f"http://{remote_host}:{remote_port}/"
    headers = {
        'accept': 'application/json',
    }
    count = 0
    while True:
        await asyncio.sleep(waiting)
        print(f"{count}\t{service_name}: {message}!")
        await get(url, headers)
        count += 1

async def run_webserver():
    config = uvicorn.Config(app, host=host, port=port)
    server = uvicorn.Server(config)
    await server.serve()

async def main():
    # 尝试使用uvloop提升性能
    try:
        import uvloop
        asyncio.set_event_loop_policy(uvloop.EventLoopPolicy())
    except ImportError:
        # 若uvloop未安装,使用默认事件循环
        pass
    await asyncio.gather(
        toc_toc("How are you"),
        run_webserver()
    )

额外说明

  • 安装依赖:执行pip install httpx uvloop以获取所需的异步库;
  • 调整并发数:Semaphore的数值可根据服务器性能和实际负载需求调整,避免过大或过小;
  • 监控请求状态:可添加请求超时设置(如httpx.AsyncClient(timeout=5)),防止单个请求阻塞过久。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 02:10:18