1.1 资源隔离的核心概念
资源隔离是保障 API 稳定性的基石,核心目标是通过逻辑隔离防止高并发场景下的资源耗尽问题。在 FastAPI 中主要体现为:
- 路由隔离:区分关键业务接口(如支付)和非关键接口(如日志查询),通过优先级队列避免低优先级请求阻塞核心服务。
- 依赖隔离 :通过
dependencies
参数限定特定路由的依赖注入范围,例如数据库连接池独立分配。
隔离实现
graph TD
A[客户端请求] --> B{路由分类}
B -->|关键路径| C[专属线程池]
B -->|非关键路径| D[公共线程池]
C --> E[数据库连接池A]
D --> F[数据库连接池B]
1.2 限流策略深度解析
限流通过控制请求速率保护系统,常用算法包括:
- 令牌桶算法:以固定速率生成令牌桶,请求消耗令牌,桶空时拒绝请求(处理突发流量)。
graph LR
A["令牌生成器"] -->|"每 t 秒生成 1 个"| B["令牌桶"]
B --> C{"桶满?"}
C -->|是| D["丢弃新令牌"]
C -->|否| E["保存令牌"]
F["用户请求"] --> G{"桶中有令牌?"}
G -->|是| H["取走令牌 处理请求"]
G -->|否| I["拒绝请求"]
特点:
- 允许突发流量(当桶中有令牌时)
- 精确控制平均请求速率
- 平滑流量曲线
- 滑动窗口算法:统计单位时间内的请求量,超过阈值即熔断(精度高但消耗内存)。
graph TB
A[请求到达] --> B{"当前窗口请求数 < 阈值?"}
B -->|是| C[计数+1 处理请求]
B -->|否| D[拒绝请求]
E[时间窗口滑动] --> F[清除过期计数]
优势:
- 避免固定窗口的临界突变问题
- 内存占用更高效
- 适合分布式环境
FastAPI 限流实战
python
from fastapi import FastAPI, Depends, Request
from slowapi import Limiter, _rate_limit_exceeded_handler # 需安装 slowapi
from slowapi.util import get_remote_address
from slowapi.errors import RateLimitExceeded
app = FastAPI()
# 初始化限流器(内存存储)
limiter = Limiter(key_func=get_remote_address)
app.state.limiter = limiter
app.add_exception_handler(RateLimitExceeded, _rate_limit_exceeded_handler)
@app.get("/payment")
@limiter.limit("5/minute") # 每分钟最多5次请求
async def pay(request: Request):
return {"status": "success"}
# 路由级动态限流
@app.get("/status")
@limiter.limit(lambda: "10/hour" if is_peak_time() else "30/hour")
async def check_status(request: Request):
...
依赖库版本说明
bash
fastapi==0.105.0
pydantic==2.5.2
slowapi==0.1.8 # 核心限流库
redis==5.0.0 # 分布式限流需安装
2.1 分布式限流实践
当服务部署多实例时,需基于 Redis 实现全局限流:
python
from slowapi import RedisLimiter # 替换原Limiter
limiter = RedisLimiter(
key_func=get_remote_address,
storage_uri="redis://localhost:6379/0", # Redis连接
strategy="moving-window" # 滑动窗口算法
)
流量控制策略对比表
算法 | 适用场景 | 优点 | 缺点 |
---|---|---|---|
令牌桶 | 突发流量 | 允许瞬时高峰 | 响应延迟增加 |
固定窗口 | 简单配额控制 | 实现简单 | 临界点突刺 |
滑动窗口 | 精准控流 | 时间维度精确 | 内存消耗大 |
3.1 案例:电商支付系统隔离
python
from fastapi import APIRouter, Depends
from database import payment_db, log_db # 分离的数据库连接池
payment_router = APIRouter(dependencies=[Depends(verify_token)])
# 核心支付接口使用独立数据库连接池
@payment_router.post("/create-order")
async def create_order(
params: OrderSchema,
db: Session = Depends(payment_db) # 专属依赖注入
):
db.add(Order(**params.dict()))
await db.commit()
# 日志查询使用公共资源
@payment_router.get("/logs")
async def get_logs(db: Session = Depends(log_db)):
return await db.query(AuditLog).all()
Quiz 1:熔断策略设计
问题 :当 /payment 接口连续3次响应超时后,如何实现自动熔断10秒?
解析方案:
- 使用
CircuitBreaker
模式(需安装 pybreaker)
python
from pybreaker import CircuitBreaker
breaker = CircuitBreaker(fail_max=3, reset_timeout=10)
@app.get("/payment")
@limiter.limit("10/minute")
@breaker # 熔断器装饰器
async def handle_payment():
if mock_failure_condition(): # 模拟超时
raise TimeoutError
return {"data": "ok"}
- 捕获
CircuitBreakerError
返回特定 HTTP 503 状态码
Quiz 2:资源耗尽场景
问题 :当数据库连接池被日志查询请求占满时,如何确保支付接口不受影响?
解答方向:
- 使用
ThreadPoolExecutor
为不同路由分配独立线程池 - 在依赖注入中实现连接池优先级调度:
python
def high_priority_db():
return acquire_connection(pool_name="HIGH_PRIORITY_POOL")
@app.post("/payment")
async def pay(db=Depends(high_priority_db)):
...
4.1 常见报错解决方案
错误 1:429 Too Many Requests
原因 :触发了 slowapi 的限流规则
解决:
- 检查路由的
@limiter.limit()
参数是否过严 - 使用
redis-cli
查看限流计数:KEYS slowapi:*
错误 2:422 Validation Error
原因 :Pydantic 模型校验失败
预防:
python
class Item(BaseModel):
price: confloat(gt=0) # 强制价格>0
size: Literal["S", "M", "L"] # 枚举值约束