如何使用 nginx 限制 HTTP/2 的 TCP 连接?

如何使用 nginx 限制 HTTP/2 的 TCP 连接?

我想使用 nginx 作为 https 前端,并且正在寻找一种限制 TCP 连接的方法。这些限制应基于远程 IP 地址,并适用于HTTP/1.1HTTP 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;

相关内容