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

基于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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 17:07:34