我正在使用nginx代理一个运行Ruby on Rails应用程序的独角兽上游。我希望能够限制单个用户(IP地址)可以消耗的后端资源总量。通过后端资源,我的意思是用户可以同时在上游独角兽进程上运行的活动请求数。
因此,例如,如果IP地址已经有2个写入连接到特定上游,我希望任何进一步的请求由nginx排队,直到之前打开的连接之一完成。请注意,我不希望删除请求 - 它们应该等到用户的写入连接数低于2。
这样,我可以确保即使一个用户尝试了很多非常耗时的操作请求,他们也不会消耗所有可用的上游独角兽工作者,并且一些独角兽工作者仍然可以为其他用户提供服务。 / p>
似乎ngx_http_limit_conn_module可能会这样做,但文档不够明确,我无法确定。
另一种思考问题的方法是,我希望通过使服务器看起来像任何一个IP地址来防止DoS(但不是DDoS,即我一次只关心来自一个IP的DoS)能够处理N个同时发出的请求。但实际上服务器可以处理10 * N个请求,但是我将来自任何一个IP的同时请求限制为服务器实际容量的十分之一。就像普通服务器的行为一样,当超过同时工作者的数量时,请求会排队,直到之前的请求完成为止。
答案 0 :(得分:2)
您可以使用limit_req模块 http://nginx.org/en/docs/http/ngx_http_limit_req_module.html
它不限制连接数,但它限制了每秒的请求数。只需使用大突发来延迟请求而不是丢弃它们。
这里的例子。
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=2r/s;
...
server {
...
location / {
limit_req zone=one burst=50;
}
你知道平均请求处理时间是1秒,所以设置限制为2r / s只允许两个工作人员忙于这个特定的IP地址(当然,大约是)。如果请求需要0.5秒才能完成,您可以设置4r / s。
答案 1 :(得分:0)
如果您知道耗时的网址,那么您可以使用limit_req模块为长请求实现2r / s,对短请求没有限制。
http {
...
#
# Limit request processing rate or connection
# If IP address is 127.0.0.1, the limit_conn_zone will not count it.
#
geo $custom_remote_addr $custom_limit_ip {
default $binary_remote_addr;
127.0.0.1 "";
}
limit_req_zone $custom_limit_ip zone=perip:10m rate=2r/s;
...
server {
...
# By default, do not enforce the maximum allowed number of connections for the remote IP
set $custom_remote_addr 127.0.0.1;
# If the URI matches a super time consuming requests, limit to 2r/s.
if ($uri ~* "^/super-long-requests") {
set $custom_remote_addr $remote_addr;
}
limit_req zone=perip burst=50;
...
}
}