我之前的回答有效,但它更适合所有请求都需要放慢速度的情况。从那以后,我不得不想出一个解决方案,让我只能根据具体情况打开速率限制,并提出以下配置。在使用它之前,请务必阅读整个答案,因为有一些重要的细微差别需要知道。
location / {
if (-f somewhere/sensible/LIMIT) {
echo_sleep 1;
# Yes, we need this here too.
echo_exec /proxy$request_uri;
}
echo_exec /proxy$request_uri;
}
location /proxy/ {
internal;
# Ultimately, all this goes to a Django server.
proxy_pass http://django/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $remote_addr;
}
重要说明:各种路径中是否存在正斜杠会有所不同。例如proxy_pass http://django
,没有尾部斜杠的 ,与上面代码中的行不一样。
操作原理很简单。如果文件somewhere/sensible/LIMIT
存在,则匹配的请求location /
会暂停一秒钟,然后再继续。所以在我的测试套件中,当我想要网络减速时,我创建文件,当我想要消除减速时,我将其删除。(而且我有清理代码,可以在每次测试之间删除它。)理论上,我更喜欢为此使用变量而不是文件,但问题是每次请求都会重新初始化变量。所以我们不能有一个location
块来设置一个变量来关闭限制,另一个来关闭它。(这是我尝试的第一件事,但由于变量的生命周期而失败)。可能可以使用 Perl 模块或 Lua 来保存变量或摆弄 cookie,但我决定不走这些路线。
重要笔记:
echo
将模块中的指令(如echo_sleep
和echo_exec
)与导致产生响应的 nginx 的 stock 指令混合不是一个好主意。我最初echo_sleep
在一起proxy_pass
并得到了不好的结果。这就是为什么我们有将股票指令与东西location /proxy/
分开的块。(有关通过拆分块解决的类似冲突,echo
请参阅此问题。)
echo_exec
由于工作原理,内部和外部的两个指令if
是必需的if
。
该internal
指令阻止客户端直接请求/proxy/...
URL。