ITPub博客

首页 > 应用开发 > XML/XSL > 核心理念:为什么是“API网关 + Serverless计算

核心理念:为什么是“API网关 + Serverless计算

投稿 XML/XSL 作者:ecclw459 时间:2026-01-29 16:01:14 0 删除 编辑

传统的多Worker部署(如Gunicorn + Uvicorn)在面对有状态计算或需要共享缓存时,复杂度会急剧上升。我们的新思路是:

- 让FastAPI本身只做它最擅长的事:成为一个纯粹的、无状态的 异步API网关。负责路由、基础验证、协议转换和异步任务编排。

- 将重型计算“外包”:把CPU密集型、机器学习推理、复杂数据处理等任务,交给专用的 Serverless函数或 高性能后端服务(如Go/ Rust服务)。

- Python作为“超级胶水”:利用 async/await非阻塞地并发调用这些后端服务,完美发挥其 IO密集型场景下的高并发优势。

这样,API层无需管理计算进程和缓存,可以轻松水平扩展。而计算服务也可以独立伸缩,通过Redis等外部存储共享状态,架构更清晰。


要实现千级并发,关键在于不让任何线程或进程“空等”。以下是如何实践:

1. 使用纯异步驱动与HTTP客户端

避免使用同步的数据库驱动或 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. 核心路由:聚合用户画像 @app.get( "/user/profile/{user_id}") 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. 健康检查(确保下游服务可用) @app.get( "/health") 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/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论

注册时间:2026-01-07

  • 博文量
    108
  • 访问量
    102104