【问题标题】:How to publish effectively to graphql subscribers when backend scaled后端扩展时如何有效地发布给graphql订阅者
【发布时间】:2020-11-02 16:57:36
【问题描述】:

我有我的后端副本以提供水平缩放。后端有 apollo graphql 订阅。还有一个为特定订阅提供通知的微服务。

由于我没有在后端保留任何状态,因此我尝试通过实现 Redis PUB/SUB 来解决问题。微服务收到事件后,会发布到后端。

在我的后端订阅解析器中

webhookCalled: {
    subscribe: withFilter(
            () => pubsubMyEvent.asyncIterator([MY_EVENT]),
            (payload, _, context) => {
                return context.dataValues.id == payload.userid;
            }
        )
    }

在上面的代码中,我试图过滤掉未发送到有效负载的订阅。我不太确定withFilter 例程的成本有多大。 当我从 Redis 收到 PUB 时,我正在打电话

pubsubMyEvent.publish(MY_EVENT, { myEventData });

这里我不喜欢的是每个后端都会处理(publish(...))所有事件,即使最后只有一个后端会真正将订阅消息发送到 graphql 客户端。

问题:如何有效地处理向 graphql 订阅客户端发送事件,同时拥有可扩展的后端?当需要通知单个 websocket 连接时,也许不要打扰所有后端副本。我是否应该跟踪 Redis 中所有连接的客户端,以便 Redis 知道每个 graphql 订阅客户端的连接位置?

【问题讨论】:

    标签: javascript redis graphql apollo-server


    【解决方案1】:

    将发布的事件发送给订阅同一频道的所有客户端是redis的本质。

    保持相同架构的可能解决方案是为每个用户使用不同的频道,而不是只使用一个频道。新用户连接后,支持者应订阅频道MY_EVENT + user.uuid,并在用户断开连接后退订同一频道。另一方面,一旦调用 webhook,服务不应在全局频道上发布,而应在 MY_EVENT + user.uuid 频道上发布。

    【讨论】:

    • 这意味着我需要一些看门狗服务,以防其中一个后端消失或应用程序崩溃,取消订阅该节点上的用户或所有用户。连接数应严格同步才能正常工作。
    • 对不起@Pablo 什么应用程序?我想是通过 WS 连接到后端的 Web 客户端。无论如何,由于注册到通道的是后端,所以当后端崩溃时,它不需要取消订阅,并且在另一个套接字端,redis 将丢弃所有由崩溃的后端保持活动状态的通道。当应用程序崩溃时,由后端取消注册(无论如何您都需要ws.on("close", handleUnregister()))。不需要看门狗服务。最后,连接数不变,通道是连接中的逻辑。
    • 它是网络浏览器或移动应用程序,使用相同的 websocket 连接。很高兴知道 redis 会放弃订阅。谢谢
    • 好的@Pablo,所以我的假设是正确的。您是否同意我的提案不需要任何看门狗服务,或者您是否发现其他问题?
    • 虽然这是合法的解决方案,但如果我使用 PubSub 的 Redis 实现与我使用默认 EventEmitter 的图表相比,似乎有本地方法可以完成此任务。
    猜你喜欢
    • 2013-01-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-09-20
    • 1970-01-01
    • 2011-11-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多