|
|
# 限流器配置说明
|
|
|
|
|
|
## 📋 概述
|
|
|
|
|
|
项目使用 Flask-Limiter 实现 API 限流功能,支持基于 Flask 配置的动态设置。
|
|
|
|
|
|
## 🔧 配置项
|
|
|
|
|
|
### 基础配置
|
|
|
|
|
|
| 配置项 | 类型 | 默认值 | 说明 |
|
|
|
|--------|------|--------|------|
|
|
|
| `RATELIMIT_ENABLED` | bool | `True` | 是否启用限流 |
|
|
|
| `RATELIMIT_STORAGE_URL` | str | `"memory://"` | 存储后端 URI |
|
|
|
| `RATELIMIT_DEFAULT` | str | `"200 per hour"` | 默认限流规则 |
|
|
|
|
|
|
### 环境配置
|
|
|
|
|
|
#### 开发环境 (DevConfig)
|
|
|
```python
|
|
|
RATELIMIT_ENABLED = True
|
|
|
RATELIMIT_STORAGE_URL = "memory://"
|
|
|
RATELIMIT_DEFAULT = "1000 per hour" # 宽松限制
|
|
|
```
|
|
|
|
|
|
#### 测试环境 (TestConfig)
|
|
|
```python
|
|
|
RATELIMIT_ENABLED = False # 禁用限流
|
|
|
```
|
|
|
|
|
|
#### 生产环境 (ProdConfig)
|
|
|
```python
|
|
|
RATELIMIT_ENABLED = True
|
|
|
RATELIMIT_STORAGE_URL = os.getenv("REDIS_URL", "memory://")
|
|
|
RATELIMIT_DEFAULT = "100 per hour" # 严格限制
|
|
|
```
|
|
|
|
|
|
## 🚀 使用方式
|
|
|
|
|
|
### 1. 基本使用
|
|
|
|
|
|
```python
|
|
|
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. 使用默认限流
|
|
|
|
|
|
```python
|
|
|
@app.route('/api/public')
|
|
|
def public_api():
|
|
|
# 使用配置中的默认限流规则
|
|
|
return jsonify({'message': 'Public API'})
|
|
|
```
|
|
|
|
|
|
### 3. 豁免限流
|
|
|
|
|
|
```python
|
|
|
@app.route('/api/health')
|
|
|
@limiter.exempt # 豁免限流
|
|
|
def health_check():
|
|
|
return jsonify({'status': 'healthy'})
|
|
|
```
|
|
|
|
|
|
### 4. 自定义键函数
|
|
|
|
|
|
```python
|
|
|
@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
|
|
|
# .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
|
|
|
```
|
|
|
|
|
|
### 使用环境变量
|
|
|
|
|
|
```bash
|
|
|
# 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
|
|
|
```
|
|
|
|
|
|
## 📊 存储后端
|
|
|
|
|
|
### 内存存储 (开发环境)
|
|
|
```python
|
|
|
RATELIMIT_STORAGE_URL = "memory://"
|
|
|
```
|
|
|
- ✅ 简单快速
|
|
|
- ❌ 重启后数据丢失
|
|
|
- ❌ 不支持多进程
|
|
|
|
|
|
### Redis 存储 (生产环境)
|
|
|
```python
|
|
|
RATELIMIT_STORAGE_URL = "redis://localhost:6379/0"
|
|
|
```
|
|
|
- ✅ 持久化存储
|
|
|
- ✅ 支持多进程
|
|
|
- ✅ 高性能
|
|
|
- ⚠️ 需要 Redis 服务
|
|
|
|
|
|
### 其他存储选项
|
|
|
```python
|
|
|
# Memcached
|
|
|
RATELIMIT_STORAGE_URL = "memcached://localhost:11211"
|
|
|
|
|
|
# 文件存储
|
|
|
RATELIMIT_STORAGE_URL = "file:///tmp/limiter.db"
|
|
|
```
|
|
|
|
|
|
## 🎯 限流规则语法
|
|
|
|
|
|
### 时间单位
|
|
|
- `second` / `sec` - 秒
|
|
|
- `minute` / `min` - 分钟
|
|
|
- `hour` - 小时
|
|
|
- `day` - 天
|
|
|
- `month` - 月
|
|
|
- `year` - 年
|
|
|
|
|
|
### 示例规则
|
|
|
```python
|
|
|
"10 per second" # 每秒10次
|
|
|
"100 per minute" # 每分钟100次
|
|
|
"1000 per hour" # 每小时1000次
|
|
|
"10000 per day" # 每天10000次
|
|
|
```
|
|
|
|
|
|
### 复杂规则
|
|
|
```python
|
|
|
"10 per minute; 100 per hour" # 每分钟10次,每小时100次
|
|
|
"5 per minute; 50 per hour; 500 per day" # 多级限流
|
|
|
```
|
|
|
|
|
|
## 🔍 调试和监控
|
|
|
|
|
|
### 检查限流状态
|
|
|
|
|
|
```python
|
|
|
@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__
|
|
|
})
|
|
|
```
|
|
|
|
|
|
### 查看限流信息
|
|
|
|
|
|
```python
|
|
|
from flask_limiter.util import get_remote_address
|
|
|
|
|
|
# 获取当前用户的限流信息
|
|
|
limits = limiter.get_window_stats(get_remote_address())
|
|
|
print(f"剩余请求: {limits[1] - limits[0]}")
|
|
|
```
|
|
|
|
|
|
## 🛠️ 故障排查
|
|
|
|
|
|
### 问题 1: 限流不生效
|
|
|
|
|
|
**检查步骤:**
|
|
|
1. 确认 `RATELIMIT_ENABLED=True`
|
|
|
2. 检查存储后端是否可用
|
|
|
3. 验证限流规则语法
|
|
|
|
|
|
**调试方法:**
|
|
|
```python
|
|
|
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 连接失败
|
|
|
|
|
|
**检查步骤:**
|
|
|
1. 确认 Redis 服务运行
|
|
|
2. 检查连接字符串格式
|
|
|
3. 验证网络连接
|
|
|
|
|
|
**解决方案:**
|
|
|
```python
|
|
|
# 使用内存存储作为后备
|
|
|
RATELIMIT_STORAGE_URL = os.getenv("REDIS_URL", "memory://")
|
|
|
```
|
|
|
|
|
|
### 问题 3: 限流过于严格
|
|
|
|
|
|
**调整方法:**
|
|
|
```python
|
|
|
# 在配置中调整
|
|
|
RATELIMIT_DEFAULT = "1000 per hour" # 更宽松的限制
|
|
|
|
|
|
# 或在路由中覆盖
|
|
|
@limiter.limit("500 per hour")
|
|
|
def my_endpoint():
|
|
|
pass
|
|
|
```
|
|
|
|
|
|
## 📚 最佳实践
|
|
|
|
|
|
### 1. 环境配置
|
|
|
|
|
|
```python
|
|
|
# 开发环境 - 宽松限制
|
|
|
RATELIMIT_DEFAULT = "1000 per hour"
|
|
|
|
|
|
# 测试环境 - 禁用限流
|
|
|
RATELIMIT_ENABLED = False
|
|
|
|
|
|
# 生产环境 - 严格限制
|
|
|
RATELIMIT_DEFAULT = "100 per hour"
|
|
|
RATELIMIT_STORAGE_URL = "redis://localhost:6379/0"
|
|
|
```
|
|
|
|
|
|
### 2. 路由设计
|
|
|
|
|
|
```python
|
|
|
# 公共 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. 错误处理
|
|
|
|
|
|
```python
|
|
|
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
|
|
|
```
|
|
|
|
|
|
## 🎉 总结
|
|
|
|
|
|
现在您的项目:
|
|
|
|
|
|
1. ✅ **支持基于配置的限流** - 从 Flask 配置中读取设置
|
|
|
2. ✅ **环境特定配置** - 不同环境使用不同的限流策略
|
|
|
3. ✅ **灵活的存储后端** - 支持内存、Redis 等
|
|
|
4. ✅ **易于调试** - 提供状态检查和错误处理
|
|
|
5. ✅ **生产就绪** - 支持高并发和持久化存储
|
|
|
|
|
|
**开始使用:**
|
|
|
```python
|
|
|
from iti.applications.extensions.limit import limiter
|
|
|
|
|
|
@app.route('/api/data')
|
|
|
@limiter.limit("10 per minute")
|
|
|
def get_data():
|
|
|
return jsonify({'data': 'some data'})
|
|
|
```
|
|
|
|
|
|
就这么简单!🚀
|