我想确保某些类型的消息不会丢失,因此我应该使用Confirms (aka Publisher Acknowledgements)。
如果代理在将所述消息写入磁盘之前崩溃,则会丢失持久消息。在某些情况下,这会导致经纪人以令人惊讶的方式行事。
例如,考虑这种情况:
- 客户端将持久消息发布到持久队列
- 客户端使用队列中的消息(注意消息是持久的并且队列是持久的),但尚未确认它,
- 代理死亡并重新启动,并且
- 客户端重新连接并开始使用消息。
此时,客户端可以合理地假设消息将被再次传递。情况并非如此:重新启动导致代理丢失了消息。为了保证持久性,客户端应该使用确认。
但是,如果使用确认,发布者在收到确认之前就宕机了,并且由于某种原因(即网络故障)消息没有传递到队列中。
假设我们有一个简单的 REST 端点,我们可以在其中发布新的评论,并且当创建新的评论时,我们希望在队列中发布一条消息。(注意:如果我发送一条新评论的消息,例如由于回滚而最终没有创建,这并不重要)。
CommentEndpoint {
Channel channel;
post(String comment) {
channel.publish("comments-queue",comment) // is a persistent queue
Comment aNewComment = new Comment(comment)
repository.save(comment)
// what happens if the server where this publisher is running terminates here ?
channel.waitConfirmations()
}
}
当服务器重新启动时,通道消失了,消息永远无法传递。我想到的一种解决方案是,在重新启动后,在存储库中查询最近的评论(类似于崩溃前最后 3 分钟之间创建的评论?),并为每个评论发送一条消息并等待确认。