传统的多Worker部署(如Gunicorn + Uvicorn)在面对有状态计算或需要共享缓存时,复杂度会急剧上升。我们的新思路是:
- 让FastAPI本身只做它最擅长的事:成为一个纯粹的、无状态的 异步API网关。负责路由、基础验证、协议转换和异步任务编排。
- 将重型计算“外包”:把CPU密集型、机器学习推理、复杂数据处理等任务,交给专用的 Serverless函数或 高性能后端服务(如Go/ Rust服务)。
- Python作为“超级胶水”:利用
async/await非阻塞地并发调用这些后端服务,完美发挥其
IO密集型场景下的高并发优势。
这样,API层无需管理计算进程和缓存,可以轻松水平扩展。而计算服务也可以独立伸缩,通过Redis等外部存储共享状态,架构更清晰。
要实现千级并发,关键在于不让任何线程或进程“空等”。以下是如何实践:
避免使用同步的数据库驱动或
requests库,它们会阻塞整个事件循环。使用其异步版本:
# 使用异步HTTP客户端(如httpx)import httpxasync def call_external_service(data: dict): async with httpx.AsyncClient(timeout=30.0) as client: # 多个外部调用可以轻松并发执行
response = await client.post("https://your-compute-service/run", json=data) return response.json()# 使用异步数据库驱动(如asyncpg for PostgreSQL, aiomysql for MySQL)import asyncpgasync def fetch_user(db_pool: asyncpg.Pool, user_id: int): async with db_pool.acquire() as connection:
# 使用异步HTTP客户端(如httpx) import httpx async def call_external_service ( data: dict ): async with httpx.AsyncClient(timeout= 30.0 ) as client: # 多个外部调用可以轻松并发执行 response = await client.post( "https://your-compute-service/run" , json=data) return response.json() # 使用异步数据库驱动(如asyncpg for PostgreSQL, aiomysql for MySQL) import asyncpg async def fetch_user ( db_pool: asyncpg.Pool, user_id: int ): async with db_pool.acquire() as connection:
# 假设这三个调用彼此独立 user_info_future = get_user_from_db(user_id) m.cqjuan.cn order_history_future = get_orders_from_service(user_id) messages_future =m.gzsrhshjjy.com get_messages_from_inbox(user_id) # 并发执行,总耗时约等于最慢的那个IO操作 user_info, orders, messages = await asyncio.gather( user_info_future, order_history_future, messages_future ) return { "info" : user_info, "orders" : orders, "messages" : messages}
2. 异步网关 (FastAPI):
- 验证JWT令牌、解析参数。
- 可能并发发起多个异步调用:从
Redis获取会话缓存,从
PostgreSQL读取基础数据。
- 将核心计算任务封装成消息,发送到
消息队列 (如RabbitMQ/Kafka),或直接异步调用
Serverless函数 (如AWS Lambda HTTP端点)。
3. 计算层 (Serverless/高性能后端):
- 函数或服务从队列拉取任务或接收HTTP调用,执行CPU密集型计算。
- 将结果写回
Redis或
对象存储 (如S3/MinIO),并通知完成。
4. 响应聚合 (FastAPI):
- 通过
WebSocket或
长轮询等待结果,或直接返回“任务已接收”的应答。
- 最终将来自数据库、缓存和计算服务的多个结果聚合,返回给客户端。
from
fastapi
import
FastAPI, Depends, HTTPException
import
httpx
import
asyncio
from
typing
import
List
app = FastAPI(title=
"异步编排网关"
)
# 1. 定义异步依赖项(如获取HTTP客户端)
async
def
get_http_client
() -> httpx.AsyncClient:
async
with
httpx.AsyncClient()
as
client:
yield
client
# 2. 核心路由:聚合用户画像
async
def
get_user_profile
(
user_id:
int,
client: httpx.AsyncClient = Depends(
get_http_client)
):
"""并发查询用户的基础信息、订单和推荐内容"""
try
:
# 定义要并发调用的服务URL
services = {
"basic_info"
:
f"http://user-service:8001/internal/users/
{user_id}"
,
"order_summary"
:
f"http://order-service:8002/internal/orders?user_id=
{user_id}&limit=5"
, gzsrhshjjy.com
"recommendations"
:
f"http://ai-service:8003/internal/recommend/
{user_id}"wap.cqjuan.cn
}
# 并发发起所有HTTP请求
tasks = {name: client.get(url)
for
name, url
in
services.items()}
responses =
await
asyncio.gather(*tasks.values(), return_exceptions=
True
)
# 处理结果
result = {}
for
(name, task), resp
in
zip
(tasks.items(), responses):
if
isinstance
(resp, Exception):
# 优雅降级:某个服务失败不影响其他数据返回
result[name] = {
"error"
:
str
(resp)}
continue
if
resp.status_code ==
200
:
result[name] = resp.json()
else
:
result[name] =
None
return
{
"user_id"
: user_id,
"profile"
: result}
except
Exception
as
e:
raise
HTTPException(status_code=
500
, detail=
f"内部编排错误:
{e}"
)
# 3. 健康检查(确保下游服务可用)
async
def
health_check
(
client: httpx.AsyncClient = Depends(
get_http_client)
):
services = [
"http://user-service:8001/health"
,
"http://order-service:8002/health"
]
tasks = [client.get(url)
for
url
in
services]
health_statuses =
await
wap.gzsrhshjjy.com asyncio.gather(*tasks, return_exceptions=
True
)
all_healthy =
all
( cqjuan.cn
isinstance
(status, httpx.Response)
and
status.status_code ==
200
for
status
in
health_statuses
)
return
{
"status"
:
"healthy"
if
all_healthy
else
"degraded"
,
"details"
: health_statuses}
来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/70048957/viewspace-3109413/ ,如需转载,请注明出处,否则将追究法律责任。