如何使用 nginx 或 haproxy 对并发会话进行速率限制?

如何使用 nginx 或 haproxy 对并发会话进行速率限制?

我目前正在使用 nginx 对进行长轮询的 Web 客户端的上游请求进行反向代理。

由于我们正在进行长轮询(而不是 websockets),当客户端连接时,它将以串行方式与服务器建立多个 http 连接,每次服务器向其发送一些数据时都会重新建立连接(或者如果服务器 10 秒内没有任何消息,则超时并重新建立连接)。

我想做的是限制并发的 Web 客户端数量。由于客户端不断发出新的 HTTP 请求,而不是保持单个请求打开,因此计算 Web 客户端的总数有点棘手(因为它与并发连接的 http 客户端的总数不同)。

我想到的方法是跟踪来自源 IP 地址的 http 请求,并将 IP 地址存储在 TTL 为 20 秒的地方。如果收到无法识别 IP 的请求,我们会检查存储的未过期 IP 地址总数;如果总数小于最大值,我们会允许此请求通过。如果收到的请求带有我们可以在查找表中找到的尚未过期的 IP 地址,那么也会允许其通过。所有允许通过的请求的 IP 都会添加到表中(如果之前没有添加),并且 TTL 会再次刷新为 20 秒。

我实际上已经用 nginx 和Redis 2.0 Nginx 模块(以及nginx lua模块来简化条件分支),使用 redis 以 TTL 存储我的 IP 地址(命令SETEX),并使用命令检查表大小DBSIZE

这有效,但性能很糟糕。nginx 和 redis 最终使用了大量 CPU,并且机器只能处理极少量的并发请求。

stick-table在 1.5 版中添加到 Haproxy 的新跟踪计数器(通过来自 serverfault 的佣金) 似乎可能是实现这种速率限制的理想选择,因为 stick-table 可以跟踪 IP 地址并自动使条目过期。但是,我没有看到一种简单的方法来获取 stick 表中未过期条目的总数,这对于了解连接的 Web 客户端数量是必要的。

我很好奇是否有人对 nginx 或 haproxy 有任何建议,或者甚至对这里未提及的其他我还没有想到的东西有任何建议。

答案1

令人惊讶的是,目前没有任何内容可以报告用于 ACL 的 stick-table 中的条目数量,尽管如果有帮助的话,这可能是一个 10 行补丁,可以添加到 haproxy 1.5 中。

如果你碰巧自己做了,请发给我,我会将其合并到主线中。否则请将我移出列表,这样我就不会忘记添加它。

相关内容