我在使消息传递在聊天系统中无法通过故障时遇到严重的问题。
我拥有多个node.js
并通过websocket
与客户端进行实时通信,因此我使用rabbit
在特定节点上回调正确的使用者。
我将队列声明为{durable: true, prefetch:1, expires: 2*3600*1000, autoDelete: true}
consumerOption为{noAck: false, exclusive: false}
一旦我收到来自服务器的消息,便回调服务器,获取消息,然后使用message.ack(false)
有时,会出现一条消息,在兔子中出现悬挂式ACK,并且正如我所期望的那样,消费者不再被回调。
这是我的总体策略:
1-当套接字断开连接时,我在重新连接/连接期间使用queue.recover()
恢复队列(更频繁)。
2-当我向服务器发送消息而又没有收到消息时,我向服务器发送消息以恢复队列。
3-我使用套接字回调函数发送ack确认。在服务器上,我使用message.ack(false)
服务器保留哈希图{[ackCode: string]: RabbitMessage}
,然后将ackCode发送回服务器,以便它可以检索正确的消息并对其进行确认。
5-如果客户端2分钟未收到任何消息,我要求服务器恢复队列。
第5步应该不存在,但是即使有这一步,有时我也会向服务器发送恢复队列请求,服务器执行命令,但是什么也没有发生,并且聊天被冻结。
这些是很难调试的事件。我使用的是打字脚本library,使用了三年,没有任何提交,这可能是原因之一。
关于策略,这是正确的吗?对我可能面对的事情有任何想法吗?
答案 0 :(得分:0)
我学到的东西以及为什么我不能使用rabbit
解决原始帖子中提到的特定问题。
域:“聊天”中的消息顺序非常重要(有些是连锁),我们必须确保如果/当客户端在线时,消息将被传递。
>问题:我们有几个node.js服务器,套接字分布在其中。套接字一直处于断开状态,对于第一个服务器中的客户端连接在另一个服务器中再次连接是很常见的。我们不使用cookie,基于IP的会话相似性将无法解决问题。
限制:就是说,我无法激活当前在另一台服务器上激活的使用者,因此如果客户队列与服务器1绑定,则无法在服务器2上激活它然后,所有需要发送的消息都绑定到此特定队列。
另一个限制是,我没有一种简单的方法来使用队列,重新排队,提前知道队列中没有ack
条消息,将它们聚合并通过套接字批量发送的数量
解决方案:我不再使用{noAck: false}
,而是在Redis队列中控制ack。因此,我将Rabbit用作发布订阅,以回调正确的使用者以使用套接字发送消息。兔子叫醒我,我要做的第一件事就是将消息放在redis队列的末尾。当我通过套接字发送消息时,我总是从队列的开头开始发送消息,而不管刚刚唤醒我的消息是什么。我发送消息,等待回调事件,如果不能,请重新排队消息,
将pub-sub与queue/ack
控件解耦之后,我现在可以轻松地将我的Rabbit pub / sub从一台服务器更改为另一台服务器(声明使用socket.id
,并且不再使用客户端队列),无需担心丢失任何消息。而且,现在我可以对队列进行更高级的操作了。
由于我的用例不允许我使用交换/绑定的全部功能(我有复杂的路由规则),因此我正在评估从Rabbit更改为Redis pub / sub的可能性,但是在这种情况下,我会继续区分发布/订阅和队列。
经过一个多月的尝试,让兔子在这种环境下工作,我认为我在错误的用例上使用了很好的技术。现在要简单得多。