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.
iTi-Flask/docs/LIMITER_CONFIG.md

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: 限流不生效

检查步骤:

  1. 确认 RATELIMIT_ENABLED=True
  2. 检查存储后端是否可用
  3. 验证限流规则语法

调试方法:

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. 验证网络连接

解决方案:

# 使用内存存储作为后备
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

🎉 总结

现在您的项目:

  1. 支持基于配置的限流 - 从 Flask 配置中读取设置
  2. 环境特定配置 - 不同环境使用不同的限流策略
  3. 灵活的存储后端 - 支持内存、Redis 等
  4. 易于调试 - 提供状态检查和错误处理
  5. 生产就绪 - 支持高并发和持久化存储

开始使用:

from iti.applications.extensions.limit import limiter

@app.route('/api/data')
@limiter.limit("10 per minute")
def get_data():
    return jsonify({'data': 'some data'})

就这么简单!🚀