为网站API设置合理的IP请求频率限制是保障系统稳定性、防止滥用和抵御DDoS攻击的重要措施。以下是详细的策略和实现方法:
一、确定限流目标
-
保护后端资源
防止过多请求压垮数据库、服务器或第三方服务。 -
防止恶意行为
如暴力破解、爬虫抓取、刷接口等。 -
公平使用资源
确保所有用户/客户端有相对公平的访问机会。
二、常见限流策略(按粒度)
| 策略 | 描述 | 适用场景 |
|---|---|---|
| 固定窗口(Fixed Window) | 每固定时间窗口内允许N次请求,如每分钟100次 | 实现简单,但存在“突发”问题 |
| 滑动窗口(Sliding Window) | 统计最近N秒内的请求数,更平滑 | 更精确控制,适合高精度限流 |
| 漏桶算法(Leaky Bucket) | 请求以恒定速率处理,超出部分排队或拒绝 | 流量整形,平滑输出 |
| 令牌桶(Token Bucket) | 按速率生成令牌,请求需消耗令牌 | 允许一定突发流量,灵活 |
推荐:令牌桶或滑动窗口用于大多数API场景。
三、合理设置限流参数
1. 基础指标参考
- 普通用户API:100~500 次/分钟
- 高频公开接口(如天气):1000~5000 次/小时
- 登录/验证码类接口:5~10 次/分钟(防暴力破解)
- 管理后台接口:更低频,如 60 次/小时
2. 分层策略(建议)
未认证用户:较低限流(如 60 次/小时)
已认证用户:中等限流(如 1000 次/小时)
VIP/API Key 用户:更高配额(可配置)
四、技术实现方式
1. 使用中间件(推荐)
Node.js (Express + Redis) 示例:
const rateLimit = require('express-rate-limit');
const RedisStore = require('rate-limit-redis');
const limiter = rateLimit({
store: new RedisStore({
prefix: 'rl:',
sendCommand: /* redis client send command */
}),
windowMs: 15 * 60 * 1000, // 15分钟
max: 100, // 最多100次
message: { error: '请求过于频繁,请稍后再试' },
standardHeaders: true,
legacyHeaders: false,
});
app.use('/api/', limiter);
2. Nginx 限流
http {
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
server {
location /api/ {
limit_req zone=api burst=20 nodelay;
proxy_pass http://backend;
}
}
}
3. 云服务方案
- AWS API Gateway:支持每API Key的限流
- Cloudflare:提供WAF和Rate Limiting规则
- 阿里云API网关:内置精细化限流策略
五、高级优化策略
-
动态限流
- 根据服务器负载自动调整阈值
- 使用Prometheus + 自定义控制器实现
-
分接口限流
- 敏感接口(如登录)单独设置更严格规则
- 读写分离:读接口宽松,写接口严格
-
白名单机制
- 内部IP、可信客户端不参与限流
白名单IP:192.168.1.0/24, CDN回源IP
- 内部IP、可信客户端不参与限流
-
异常检测联动
- 连续触发限流的IP加入短期黑名单(如Redis记录+自动封禁)
六、响应与用户体验
- 返回标准HTTP状态码:
429 Too Many Requests
- 响应头包含:
Retry-After: 60 X-RateLimit-Limit: 100 X-RateLimit-Remaining: 2 X-RateLimit-Reset: 1700000000 - 提供清晰错误信息,引导用户等待或升级权限
七、监控与调优
- 记录被限流的请求日志
- 可视化仪表盘(如Grafana)展示:
- 各IP请求频率分布
- 限流触发次数趋势
- 定期分析日志,调整阈值避免误伤正常用户
总结
✅ 最佳实践要点:
- 使用 Redis + 令牌桶/滑动窗口 实现精准限流
- 对不同用户/接口分级限流
- 返回标准429状态码和限流信息头
- 结合白名单、异常检测提升安全性
- 持续监控并动态优化策略
合理限流不是一味收紧,而是在安全与可用性之间取得平衡。建议从保守策略开始,逐步根据实际流量模式调整。
云小栈