forked from iti-framework/iTi-Flask
You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
6.2 KiB
6.2 KiB
限流器配置说明
📋 概述
项目使用 Flask-Limiter 实现 API 限流功能,支持基于 Flask 配置的动态设置。
🔧 配置项
基础配置
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
RATELIMIT_ENABLED |
bool | True |
是否启用限流 |
RATELIMIT_STORAGE_URL |
str | "memory://" |
存储后端 URI |
RATELIMIT_DEFAULT |
str | "200 per hour" |
默认限流规则 |
环境配置
开发环境 (DevConfig)
RATELIMIT_ENABLED = True
RATELIMIT_STORAGE_URL = "memory://"
RATELIMIT_DEFAULT = "1000 per hour" # 宽松限制
测试环境 (TestConfig)
RATELIMIT_ENABLED = False # 禁用限流
生产环境 (ProdConfig)
RATELIMIT_ENABLED = True
RATELIMIT_STORAGE_URL = os.getenv("REDIS_URL", "memory://")
RATELIMIT_DEFAULT = "100 per hour" # 严格限制
🚀 使用方式
1. 基本使用
from flask import Flask, jsonify
from iti.applications.extensions.limit import limiter
app = Flask(__name__)
@app.route('/api/data')
@limiter.limit("10 per minute") # 每分钟10次
def get_data():
return jsonify({'data': 'some data'})
2. 使用默认限流
@app.route('/api/public')
def public_api():
# 使用配置中的默认限流规则
return jsonify({'message': 'Public API'})
3. 豁免限流
@app.route('/api/health')
@limiter.exempt # 豁免限流
def health_check():
return jsonify({'status': 'healthy'})
4. 自定义键函数
@app.route('/api/user-data')
@limiter.limit("50 per hour", key_func=lambda: "user_123")
def user_data():
return jsonify({'user': 'user_123', 'data': 'user data'})
🔧 配置示例
使用 .env 文件
# .env
RATELIMIT_ENABLED=true
RATELIMIT_STORAGE_URL=memory://
RATELIMIT_DEFAULT=200 per hour
# .env.prod
RATELIMIT_ENABLED=true
RATELIMIT_STORAGE_URL=redis://localhost:6379/0
RATELIMIT_DEFAULT=100 per hour
使用环境变量
# Windows
set RATELIMIT_ENABLED=true
set RATELIMIT_STORAGE_URL=redis://localhost:6379/0
set RATELIMIT_DEFAULT=100 per hour
# Linux/macOS
export RATELIMIT_ENABLED=true
export RATELIMIT_STORAGE_URL=redis://localhost:6379/0
export RATELIMIT_DEFAULT=100 per hour
📊 存储后端
内存存储 (开发环境)
RATELIMIT_STORAGE_URL = "memory://"
- ✅ 简单快速
- ❌ 重启后数据丢失
- ❌ 不支持多进程
Redis 存储 (生产环境)
RATELIMIT_STORAGE_URL = "redis://localhost:6379/0"
- ✅ 持久化存储
- ✅ 支持多进程
- ✅ 高性能
- ⚠️ 需要 Redis 服务
其他存储选项
# Memcached
RATELIMIT_STORAGE_URL = "memcached://localhost:11211"
# 文件存储
RATELIMIT_STORAGE_URL = "file:///tmp/limiter.db"
🎯 限流规则语法
时间单位
second/sec- 秒minute/min- 分钟hour- 小时day- 天month- 月year- 年
示例规则
"10 per second" # 每秒10次
"100 per minute" # 每分钟100次
"1000 per hour" # 每小时1000次
"10000 per day" # 每天10000次
复杂规则
"10 per minute; 100 per hour" # 每分钟10次,每小时100次
"5 per minute; 50 per hour; 500 per day" # 多级限流
🔍 调试和监控
检查限流状态
@app.route('/api/limiter-status')
def limiter_status():
if limiter is None:
return jsonify({'enabled': False})
return jsonify({
'enabled': True,
'default_limits': limiter.default_limits,
'storage_uri': limiter.storage_uri,
'key_func': limiter.key_func.__name__
})
查看限流信息
from flask_limiter.util import get_remote_address
# 获取当前用户的限流信息
limits = limiter.get_window_stats(get_remote_address())
print(f"剩余请求: {limits[1] - limits[0]}")
🛠️ 故障排查
问题 1: 限流不生效
检查步骤:
- 确认
RATELIMIT_ENABLED=True - 检查存储后端是否可用
- 验证限流规则语法
调试方法:
print(f"限流启用: {app.config.get('RATELIMIT_ENABLED')}")
print(f"存储URI: {app.config.get('RATELIMIT_STORAGE_URL')}")
print(f"默认限制: {app.config.get('RATELIMIT_DEFAULT')}")
问题 2: Redis 连接失败
检查步骤:
- 确认 Redis 服务运行
- 检查连接字符串格式
- 验证网络连接
解决方案:
# 使用内存存储作为后备
RATELIMIT_STORAGE_URL = os.getenv("REDIS_URL", "memory://")
问题 3: 限流过于严格
调整方法:
# 在配置中调整
RATELIMIT_DEFAULT = "1000 per hour" # 更宽松的限制
# 或在路由中覆盖
@limiter.limit("500 per hour")
def my_endpoint():
pass
📚 最佳实践
1. 环境配置
# 开发环境 - 宽松限制
RATELIMIT_DEFAULT = "1000 per hour"
# 测试环境 - 禁用限流
RATELIMIT_ENABLED = False
# 生产环境 - 严格限制
RATELIMIT_DEFAULT = "100 per hour"
RATELIMIT_STORAGE_URL = "redis://localhost:6379/0"
2. 路由设计
# 公共 API - 宽松限制
@app.route('/api/public')
@limiter.limit("100 per hour")
def public_api():
pass
# 私有 API - 严格限制
@app.route('/api/private')
@limiter.limit("10 per hour")
def private_api():
pass
# 健康检查 - 豁免限流
@app.route('/health')
@limiter.exempt
def health():
pass
3. 错误处理
from flask_limiter.errors import RateLimitExceeded
@app.errorhandler(RateLimitExceeded)
def handle_rate_limit_exceeded(e):
return jsonify({
'error': 'Rate limit exceeded',
'message': 'Too many requests',
'retry_after': e.retry_after
}), 429
🎉 总结
现在您的项目:
- ✅ 支持基于配置的限流 - 从 Flask 配置中读取设置
- ✅ 环境特定配置 - 不同环境使用不同的限流策略
- ✅ 灵活的存储后端 - 支持内存、Redis 等
- ✅ 易于调试 - 提供状态检查和错误处理
- ✅ 生产就绪 - 支持高并发和持久化存储
开始使用:
from iti.applications.extensions.limit import limiter
@app.route('/api/data')
@limiter.limit("10 per minute")
def get_data():
return jsonify({'data': 'some data'})
就这么简单!🚀