我不知道如果在这里或者在Programmers.SE上讨论这个问题更好,所以如果我有这个错误,请迁移。
首先,关于我正在尝试实施的内容。我有一个node.js应用程序从一个源(一个socket.io客户端)获取消息,然后对消息进行处理,这可能导致零个或多个消息退出,发送者或其他客户端基。
对于处理,我想基本上只是将消息推入队列,然后它通过各种消息处理器工作,可能会启动他们自己的项目,最终,运行socket.io的位被告知“嘿,发回此消息“
作为一个具体的例子,假设一个用户登录该服务,然后将登录消息放入队列中,授权处理器获取它,这样做,然后将消息放回队列中说客户端已经授权。这可以追溯到连接到客户端的socket.io套接字以及可能感兴趣的其他客户端。它还可以转到其他可能希望对授权进行更多处理的子系统(查找用户信息,根据数据向客户端发送更多信息等)。
如果我想要强耦合,这很容易,但我之前尝试过,它只是乱七八糟的意大利面条代码,非常脆弱,我想避免这种情况。设置中的另一个问题是这应该是集群能力的,这是真正的问题所在。可能有多个,例如,授权处理器正在运行。但授权消息只应处理一次。
因此,简而言之,我正在寻找一种模式/技术,这种模式/技术基本上允许我为一条消息提供多个“组”订阅者,并且每个组只会处理一次消息。
我想过可能让处理器的每个实例生成一个唯一的名称,该名称将用作Reids中的列表。然后,该名称将在某种调度处理程序中注册,并放入该订阅者组的集合中。然后,当消息到达时,调度会从该集合中拉出一个随机成员,并将其放入该列表中。虽然看起来这样可行,但似乎有点过于复杂和脆弱。
核心问题是我从来没有设计过这样的系统,所以我甚至不确定使用或查找的正确术语。如果有人能指出我正确的方向,我会非常感激。
答案 0 :(得分:2)
我认为您的描述类似于https://www.getbridge.com/服务。我最后写了自己的zeromq,它允许你注册服务,req - > < - rec和频道是pub / sub worker。
至于设计,我使用了一个客户端 - >经纪人 - >服务与使用自动发现即插即用的通道,您可以让服务向打开tcp连接的代理注册其架构,以便其他服务器上的代理可以与该代理组服务进行通信。然后内部服务和客户端通过unix套接字或ipc通道连接,这是首选。
答案 1 :(得分:2)
我最终绕过redis发布/订阅函数来执行此操作。每种类型的消息处理器都会获得一个“组名”,该组中可能有多个处理器实例(因此可以运行多个程序实例进行群集)。
发布消息时,我生成增量ID,然后将消息存储在具有该ID的字符串键中,然后发布消息ID。
在接收端,订阅者所做的第一件事是尝试将刚从发布者处获得的消息ID添加到具有sadd
的该组的一组接收消息中。如果sadd
返回0
,则该消息已被另一个实例抓取,并且它只是返回。如果它返回1
,则从字符串键中拉出完整的消息并发送给监听器。
当然,这依赖于redis是单线程的,我想这将继续如此。
答案 2 :(得分:1)
您可能正在寻找的是AMQP协议实现,您可以在其中进行队列获取自定义交换,并实现pub-sub模型。
RabbitMQ - a popular amqp protocol implementation with lots of libraries
它还有node.js库