在Flask APIs中实施速率限制
速率限制是一种在系统中限制网络流量的技术。它设定了一个限制,即用户在特定的时间范围内可以在系统中重复操作。
在这篇文章中,你将学习。
- 什么是速率限制?
- 限制网络请求率的好处。
- 速率限制技术。
- 如何在Flask APIs中实现速率限制技术。
前提条件
要遵循并完全理解本教程,你需要具备以下条件。
- Python 3.6或更新版本。
- 对Flask的基本了解。
- 一个文本编辑器。
简介
速率限制控制一个操作的重复频率,并确保指导这个操作的设定约束不被超过(通常在特定的时间范围内)。
基本上,速率限制的过程包括以下程序。
- 系统为特定的操作定义了速率限制规则。
- 系统对启动用户的每个操作或请求进行统计。
- 请求的频率根据用户的需求而增加。
- 一旦频率达到系统的阈值(速率限制),进一步的请求就不会被处理,直到限制被取消(或修改)。
速率限制的好处
- 通过缓解DDoS等网络攻击,提高安全效率。
- 防止网络刮擦/机器人/垃圾邮件用户。
- 防止服务器资源耗尽。
- 管理内部/外部服务、政策和配额。
- 控制系统进程和数据的流动。
- 避免了高额的维护费用。
Flask网络框架
Flask是一个用Python编写的轻量级网络框架。它旨在使使用Python的网络开发变得快速和简单,并能建立复杂的应用程序。
速率限制技术
在一般情况下,速率是对系统中运行的操作次数的统计。有不同的技术来测量和限制速率。
它们包括。
- 固定窗口:这种技术定义了在一个特定的时间内容纳的固定数量的请求。例如,设置每小时100个请求的窗口大小,意味着系统将只处理用户在该小时内提出的前100个请求,而每一个后续请求将被丢弃,直到下一个小时。
- 滑动窗口:这种技术与固定窗口非常相似,即在一个特定的时间内允许有固定数量的请求。然而,它实现了一个滚动的时间窗口,以考虑到大量的请求高峰,这将降低固定窗口技术的效率。
- Token Bucket:在这种技术中,系统不断计算用户在其内存(桶)中可以利用的代币数量,以提出请求。每当有请求提出时,就从桶中减少代币,直到代币用完为止。这种技术的一个优点是根据进程的操作能力,为不同的操作分配不同数量的代币。
- 漏桶:这种技术与代币桶非常相似。然而,速率受限于从内存(桶)中泄漏出来的请求数量。这种技术首先确认系统有足够的处理能力来处理传入的请求,然后再进行处理,如果不能处理,就丢弃。
构建一个简单的Flask API
速率限制通常用于网络应用和API,以防止用户请求过度流入服务器。使用Python,让我们建立一个Flask API并在其中实现速率限制技术。
首先,你必须安装Flask网络框架,你将用它来构建API。
第1步
在终端中,输入。
pip install Flask
第2步
编写负责设置Flask API端点的代码。首先,创建一个名为app.py 的文件,并在其中保存以下代码。
from flask import Flask
app = Flask(__name__)
@app.route("/")
def index():
return "Welcome to my Flask API"
if __name__ == "__main__":
app.run()
在上面的代码中,你创建了一个简单的Flask应用程序,当索引路由被请求时渲染文本"Welcome to my Flask API" 。在运行Flask应用程序后,你应该得到一个类似于下图的响应。

在Flask中实现速率限制
在安装Flask框架并保存负责设置上述步骤中描述的端点的代码后,这里的下一步是安装Flask-Limiter库。
Flask-Limiter是一个Flask扩展,有助于在Flask应用程序中快速实现速率限制规则。
在终端,输入。
pip install Flask-Limiter
现在,你需要更新你的app.py 文件,并整合Flask-Limiter 库,为你的API中的特定端点定义速率限制规则。
导入Flask-Limiter库
from flask_limiter import Limiter
from flask_limiter.util import get_remote_address
设置Flask-Limiter
limiter = Limiter(app, key_func=get_remote_address)
应用速率限制规则
@app.route("/")
@limiter.limit("10/minute") # maximum of 10 requests per minute
def index():
return "Welcome to my Flask API"
在上面的代码中,你为端点定义了速率限制规则,将其设置为每60 秒接受每个API用户的请求10 。
如果超过了限制,用户就会收到响应--status code 429 (Too Many Requests) ,并出现如下图所示的错误页面。

Flask-Limiter在其[文档]中提供了一套用于定义速率限制规则的字符串符号,并给出了格式。
[count] [per|/] [n (optional)] [second|minute|hour|day|month|year]
你也可以通过用你选择的分隔符来组合多个速率限制。
例子包括。
- 10/秒
- 60/小时
- 5/秒;60/分钟;2500/小时
- 50/天,250/7天
探索Flask-Limiter的功能
我们将在本节中简要说明其中的一些功能。
设置默认费率限制规则
Flask-Limiter提供了设置默认速率限制规则的功能,Flask-Limiter将自动应用于你的Flask API中的每个端点。
要设置默认规则,请使用。
limiter = Limiter(
app,
key_func=get_remote_address,
default_limits=["200/day", "50/hour"]
)
注意:如果一个端点在默认值已经存在的情况下定义其速率限制规则,新定义的规则将单独应用于路由,而默认值将被忽略。
要使一个路由使用默认规则并同时定义自己的规则,请在装饰器中使用override_defaults 参数,如图所示。
@app.route("/ping/")
@limiter.limit("1/second", override_defaults=False)
def ping():
return "PONG"
某些端点也可以用@limiter.exempt 装饰器排除在应用默认速率限制规则之外,如图所示。
@app.route("/ping/")
@limiter.exempt
def ping():
return "PONG"
使用自定义速率限制键
默认情况下,Flask-Limiter使用请求的remote address ,以识别与API互动的每个用户。Flask-Limiter提供了使用自定义用户标识符函数的功能,用于你需要用API密钥和用户名限制费率的事件。
你可以通过在初始化限制器时或在路由上应用@limiter.limit 装饰器时将自定义函数传递给key_func 参数来实现。
limiter = Limiter(app, key_func=custom_function_here)
@limiter.limit("10/minute", key_func=custom_function_here)
注意:自定义函数是从Flask请求上下文中调用的,必须返回一个字符串。
拥有多个速率限制规则
Flask-Limiter可以用来为一个特定的路由定义多个速率限制规则。
这可以通过代码来完成。
@app.route("....") # for a single decorator
@limiter.limit("100/day;10/hour;1/minute")
@app.route("....") # for multiple decorators
@limiter.limit("100/day")
@limiter.limit("10/hour")
@limiter.limit("1/minute")
生成自定义的超过限制的响应
默认情况下,Flask-Limiter在任何特定路线的费率限制被超过时,会触发abort(429) 。你可以通过为429 error code 注册一个错误处理程序来为用户定制这个响应,如下所示。
@app.errorhandler(429)
def ratelimit_handler(e):
return "You have exceeded your rate-limit"

总结
在这篇文章中,我向你介绍了什么是速率限制,讨论了限制请求速率的重要性,包括减轻网络攻击,防止服务器资源耗尽,以及其他好处。还强调了一些标准的速率限制技术,并建立了一个Flask应用程序,在这个应用程序中,你可以通过不同的规则和自定义响应来实现速率限制技术。