我想使用 nginx 作为 https 前端,并且正在寻找一种限制 TCP 连接的方法。这些限制应基于远程 IP 地址,并适用于HTTP/1.1也HTTP 2。
为了HTTP/1.1我认为每个 IP 大约 15 个并发连接就足够了(因为大多数浏览器似乎最多使用 6 个),这应该足够了HTTP/2.但是nginx 文档状态:
在 HTTP/2 和 SPDY 中,每个并发请求被视为一个单独的连接。
还有HTTP/2 规范关于参数的说明SETTINGS_MAX_CONCURRENT_STREAMS
:
建议该值不小于 100,以免不必要地限制并行性。
这是否意味着我应该允许每个远程 IP 至少有 100 个连接?在我的测试中似乎如此,但也许我忽略了一些东西。因为这似乎意味着我不能设置任何有意义的限制并发 TCP 连接数,但不会严重限制HTTP/2。
答案1
以下是我目前解决此问题的方法:
map $http2 $v1ip {
default "";
"" $binary_remote_addr;
}
map $http2 $v2ip {
default $binary_remote_addr;
"" "";
}
limit_conn_zone $v1ip zone=v1ips:10m;
limit_conn v1ips 10;
limit_conn_zone $v2ip zone=v2ips:10m;
limit_conn v2ips 125;
由于 HTTP/2 的连接限制必须那么高,所以我还添加了速率限制......但我仍在调整这些值。
笔记:虽然这允许为 HTTP < 2 连接设置一个“合理”的值,但它仍然需要大量并发连接(在我看来是不必要的)。我非常希望limit_conn
只关注 TCP 连接而不是 HTTP 请求。
答案2
上面的解决方案非常好,如果使用白名单我认为使用“”并不好。
应该使用 $request_id 来代替 "" 会更好
geo $whitelist {
default 0;
127.0.0.1/32 1;
}
map $http2 $http1_ip {
default $request_id;
"" $binary_remote_addr;
}
map $http2 $http2_ip {
default $binary_remote_addr;
"" $request_id;
}
map $whitelist $http1_ip_final {
default $http1_ip;
1 $request_id;
}
map $whitelist $http2_ip_final {
default $http2_ip;
1 $request_id;
}
limit_conn_zone $http1_ip_final zone=conn_limit_per_ip_http1:10m;
limit_conn conn_limit_per_ip_http1 10;
limit_conn_zone $http2_ip_final zone=conn_limit_per_ip_http2:10m;
limit_conn conn_limit_per_ip_http2 125;