【问题标题】:How to have one Redis client wait for all the other Redis clients to respond?如何让一个 Redis 客户端等待所有其他 Redis 客户端响应?
【发布时间】:2018-04-24 11:15:07
【问题描述】:

我有一个 Redis 服务器和多个 Redis 客户端。每个 Redis 客户端都是一个 WebSocket+HTTP 服务器,其中包括管理 WebSocket 连接。这些 WebSocket+HTTP 服务器隐藏在负载均衡器后面。

WebSocket+HTTP 服务器提供GET /health HTTP 端点。我希望这个端点能够提供整个集群中当前 WebSocket 连接的总数。

当点击GET /health时,显然负载均衡器只会将请求分派给一个WebSocket+HTTP服务器实例。

如何让一个 WebSocket+HTTP 服务器实例向所有其他实例询问它们当前管理的 WebSocket 连接数?


我想到了以下步骤:

  1. 实例使用CLIENT LIST 了解当前有多少Redis 客户端(例如n);
  2. 然后实例将WEBSOCKET_CONNECTION_COUNT_REQUEST 发布到 Redis(假设所有 Redis 客户端都订阅了此事件);
  3. 实例最终等待nWEBSOCKET_CONNECTION_COUNT_RESPONSEs,汇总计数,并通过HTTP返回。

您对上述方法有何看法?是不是有点太绕了?我觉得我可能有点过度设计......


我最初认为实例可以INCR/DECR Redis 存储中的计数,但我不确定如何处理被杀死的实例(因为计数应该相应减少)。我认为临时解决方案会更好。不过仍然对想法持开放态度。

【问题讨论】:

    标签: redis load-balancing publish-subscribe health-monitoring horizontal-scaling


    【解决方案1】:

    我会使用一个排序集,其中成员是 WS 服务器 ID,分数是他们最后一次“ping”的时间戳。

    通过使用其 id 更新已排序集,让每个 WS 定期“ping”(例如每 10 秒)。您可以使用 Lua 脚本从服务器获取时间并设置成员的分数以使一切变得美好和原子:

    redis.replicate_commands()
    local t = redis.call('TIME')
    return redis.call('ZADD', KEYS[1], tonumber(t[0]), ARGV[1])
    

    因此,如果您的排序集被称为“wsservers”并且 WS 的 id 是 foo,您可以在加载脚本后使用 EVALSHA <script-sha1> 1 wsservers foo 调用它。

    要返回计数,您只需在最后一个周期(即 11 秒)的已排序集上设置一个范围并计算结果。您还可以利用这个机会来修剪旧的死服务器。当然,Lua 脚本是我的首选方法,这两项任务都无需实际将原始 WS 成员发送到调用客户端:

    local t = redis.call('TIME')
    local live = redis.call('ZRANGE', KEYS[1], tonumber(t[0])-11, '+inf')
    redis.call('ZREMRANGEBYSCORE', KEYS[1], '-inf', tonumber(t[0])-11)
    return #live
    

    【讨论】:

    • 有趣的方法,阅读时清理。你的 sn-ps 我没有得到一些东西:每台服务器的当前 WebSocket 连接数在哪里?
    • 错过了该请求 - 您可以使用相同的方法,但不要将服务器的 id 存储为元素存储连接 WS 连接 id 的东西。这样,您将拥有每个连接的唯一成员。或者,使用相同的方法,但也将带有当前连接数的字符串计数器保存在带有 TTL 的单独键中,您可以在执行 ZRANGE 后使用它来读取当前计数。
    猜你喜欢
    • 2014-01-20
    • 1970-01-01
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 1970-01-01
    • 2014-05-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多