我正在尝试用nginx(v1.6.2)
实现一个简单的速率限制系统sites-available / mysite.com :
limit_req_zone $binary_remote_addr zone=myzone:10m rate=2r/m;
server {
listen 80;
server_name mysite.com;
root /var/www/vhosts/mysite.com;
error_log [..];
access_log [..];
include conf.d/php-fpm.conf;
location = / {
limit_req zone=myzone burst=3 nodelay;
index index.html;
}
location / {
try_files $uri =404;
}
location ^~ /pages {
include conf.d/php-fpm.conf;
internal;
}
location = /email {
rewrite ^(.*)$ /pages/email.html;
}
location = /email/subscribe {
limit_req zone=myzone burst=2 nodelay;
rewrite ^(.*)$ /pages/email.php?action=subscribe;
}
location ~ /api {
limit_req zone=myzone burst=5 nodelay;
rewrite ^(.*)$ /pages/api.php;
}
}
conf.d / php-fpm.conf :
location ~ \.php$ {
if (!-f $document_root$fastcgi_script_name) {
return 404;
}
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_split_path_info ^(.+?\.php)(/.*)$;
fastcgi_param PATH_INFO $fastcgi_path_info;
include fastcgi_params;
}
nginx.conf :
没有什么有趣的,只有
include sites-enabled/*;
速率限制/
运行正常。如果我对此页面的请求过多,我会收到错误503
问题:/email/subscribe
,/api
和/api/test
都不受费率限制,我不知道原因。它必须与rewrite
做一些事情,但问题是什么?
有任何想法吗?我尝试了一切!
请注意:我已更改了文件名和网址端点。
答案 0 :(得分:4)
问题是几个phases和重写阶段的nginx进程请求在 preaccess 之前进行(这是应用limit_req
的地方) 。因此,在您配置请求被重写为/pages/...
之前,他们才有机会被限制。为了避免这种情况,您应该在重写(使用break
标志)或使用try_files
稍微破解后保留在相同的位置块中。
我更喜欢第一个选项,因此您的配置可能如下所示:
limit_req_zone $binary_remote_addr zone=myzone:10m rate=2r/m;
server {
listen 80;
server_name mysite.com;
root /var/www/vhosts/mysite.com;
error_log [..];
access_log [..];
include conf.d/php-fpm.conf;
location = / {
limit_req zone=myzone burst=3 nodelay;
index index.html;
}
location / {
try_files $uri =404;
}
location ^~ /pages {
include conf.d/php-fpm.conf;
internal;
}
location = /email {
rewrite ^(.*)$ /pages/email.html;
}
location = /email/subscribe {
limit_req zone=myzone burst=2 nodelay;
rewrite ^(.*)$ /pages/email.php?action=subscribe break;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
location ~ /api {
limit_req zone=myzone burst=5 nodelay;
rewrite ^(.*)$ /pages/api.php break;
fastcgi_pass unix:/var/run/php5-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
如果你选择第二个选项,你的配置会更干净,但有点hacky。我们将使用try_files
阶段在limit_req
阶段之后运行的事实,并且try_files
使内部重定向到它的最后一个参数。
limit_req_zone $binary_remote_addr zone=myzone:10m rate=2r/m;
server {
listen 80;
server_name mysite.com;
root /var/www/vhosts/mysite.com;
error_log [..];
access_log [..];
include conf.d/php-fpm.conf;
location = / {
limit_req zone=myzone burst=3 nodelay;
index index.html;
}
location / {
try_files $uri =404;
}
location ^~ /pages {
include conf.d/php-fpm.conf;
internal;
}
location = /email {
rewrite ^(.*)$ /pages/email.html;
}
location = /email/subscribe {
limit_req zone=myzone burst=2 nodelay;
try_files SOME_NONEXISTENT_FILE /pages/email.php?action=subscribe;
}
location ~ /api {
limit_req zone=myzone burst=5 nodelay;
try_files SOME_NONEXISTENT_FILE /pages/api.php;
}
}