基于IP计数的Python限流器应在技术栈的哪个层级实现?
基于IP计数的Python限流器层级实现建议
针对你的需求,以下是几个兼顾性能、自定义需求且避免重复造轮子的实现方案,按性能从高到低排序:
1. WSGI/ASGI服务器级中间件(最推荐)
直接在Gunicorn(WSGI)、Uvicorn(ASGI)这类Python原生Web服务器层实现中间件,比Django/Flask框架层中间件更靠近底层,性能损耗极小,同时不用重复造Web服务器轮子。
这类服务器的中间件会在请求到达框架路由前拦截处理,能直接获取源IP并执行限流逻辑:
# 以Uvicorn的ASGI中间件为例 import time from collections import defaultdict from fastapi import FastAPI from starlette.middleware.base import BaseHTTPMiddleware from starlette.requests import Request from starlette.responses import PlainTextResponse app = FastAPI() # 简单的内存计数(生产环境建议用Redis等分布式存储) ip_request_counts = defaultdict(list) RATE_LIMIT = 10 # 10次请求 TIME_WINDOW = 60 # 60秒 class IPLimiterMiddleware(BaseHTTPMiddleware): async def dispatch(self, request: Request, call_next): client_ip = request.client.host current_time = time.time() # 清理时间窗口外的请求记录 ip_request_counts[client_ip] = [t for t in ip_request_counts[client_ip] if current_time - t < TIME_WINDOW] if len(ip_request_counts[client_ip]) >= RATE_LIMIT: return PlainTextResponse("Too many requests", status_code=429) ip_request_counts[client_ip].append(current_time) response = await call_next(request) return response app.add_middleware(IPLimiterMiddleware) @app.get("/") async def root(): return {"message": "Hello World"}
这种方式既利用了成熟服务器的高性能,又用Python完全自定义限流逻辑,性能远优于框架层中间件。
2. Python轻量反向代理层
用Python实现一个轻量反向代理,集成限流逻辑后转发请求到后端服务。比如用aiohttp做异步代理,性能表现接近底层服务器,且完全由Python控制:
import time from collections import defaultdict import aiohttp from aiohttp import web ip_request_counts = defaultdict(list) RATE_LIMIT = 10 TIME_WINDOW = 60 TARGET_URL = "http://your-backend-service:8000" async def limit_middleware(app, handler): async def middleware_handler(request): client_ip = request.remote current_time = time.time() ip_request_counts[client_ip] = [t for t in ip_request_counts[client_ip] if current_time - t < TIME_WINDOW] if len(ip_request_counts[client_ip]) >= RATE_LIMIT: return web.Response(text="Too many requests", status=429) ip_request_counts[client_ip].append(current_time) # 转发请求到后端 async with aiohttp.ClientSession() as session: async with session.request( method=request.method, url=TARGET_URL + request.path, headers=request.headers, data=await request.read() ) as resp: return web.Response( body=await resp.read(), status=resp.status, headers=resp.headers ) return middleware_handler app = web.Application(middlewares=[limit_middleware]) web.run_app(app, host="0.0.0.0", port=8080)
这个方案适合需要独立于后端框架部署限流逻辑的场景,性能比框架中间件好,且无需依赖NGINX等第三方服务器。
3. NGINX + Python服务折中方案
如果已经有NGINX部署,可以用NGINX的Lua模块调用Python限流服务做判断,兼顾NGINX的高性能转发和Python的自定义逻辑:
- 先写一个简单的Python限流服务(比如用FastAPI),接收IP参数返回是否允许请求
- 在NGINX配置中用
access_by_lua_block调用该服务:
server { listen 80; server_name your-domain.com; access_by_lua_block { local client_ip = ngx.var.remote_addr local res = ngx.location.capture("/check_limit", { args = { ip = client_ip } }) if res.status ~= 200 then ngx.exit(429) end } location /check_limit { proxy_pass http://your-python-limiter-service:8000/check; internal; } location / { proxy_pass http://your-backend-service:8000; } }
这种方式让NGINX负责高性能转发,Python专注于复杂的限流逻辑,性能接近纯NGINX方案,同时满足你的自定义需求。
内容的提问来源于stack exchange,提问作者m3m3n70 m0r1
相关产品推荐
相关产品推荐

