总线实例生命周期和最佳实践

本文关键字:最佳 周期 实例 生命 总线 | 更新日期: 2023-09-27 18:15:54

在评估一般队列机制,特别是Rebus时,我提出了以下关于总线实例生命周期的问题:

  1. 当需要从托管在windows服务上的几个WCF服务访问总线实例(单向客户端模式)时,实例化的唯一选择是单例模式?

  2. 有一种方法可以暂停总线(停止向消息处理程序发送消息?),然后重新启动它。或者唯一的选择是处理它并创建一个新的。

    • 此用例是当您连接到具有吞吐量限制或每小时事务限制的系统时。
  3. 传奇可以有多个worker吗?如果可以,并且假设事件是按照正确的顺序发送的(首先是发起者),那么有办法保证在多个worker处理以下事件之前,首先处理创建传奇的发起者吗?

  4. 如果在同一主机中,使用了多个总线实例,并且在消息处理程序中,我们基于相同的配置在另一个总线实例上调用send。correlation-id不会被传输,像reply这样的东西也不会正常工作,对吧?

我更喜欢关于Rebus如何支持或不支持这一点的具体答案,带有代码参考/示例。

总线实例生命周期和最佳实践

1:这真的很简单:总线实例(即IBus的实现,它被放入容器中,当你做Configure.With(...)配置咒语时交给你)应该是一个单例实例,你在应用程序的整个生命周期中保持在周围。

您可以轻松地创建多个实例,但这只适用于在同一进程中托管多个Rebus端点。

总线是完全可重入的,并且可以安全地在web应用程序的线程之间共享。

2:不容易,不——至少在公共API支持的方式上不容易。您可以这样做:((RebusBus)bus).SetNumberOfWorkers(0)(即将IBus实例转换为RebusBus并更改工作线程的数量),这将阻塞,直到工作线程的数量被调整到所需的数量。

这样,你就能真正实现你想要的。这还不是Rebus的官方特性,但将来可能会成为。但是,我可以保证,在运行时调整工作线程数量的能力不会消失。

3:是的,无论您选择哪个持久层,传奇都由乐观并发方案保护。如果你不确定哪种类型的消息会首先到达你的saga,你应该让你的saga容忍这种情况——即为每种潜在的初始消息类型实现IAmInitiatedBy<>,并使saga正确处理。

(相当)容忍乱序消息是一个很好的通用鲁棒性原则,当消息在错误队列中停留一段时间后重新传递时,它也将很好地为您服务。

4:即使您使用多个总线实例,Rebus也会拾取当前消息上下文,因为它使用"环境上下文"(即安装在工作线程上的MessageContext实例)来拾取您从处理程序内发送消息的事实,这反过来会导致处理消息的相关ID被复制到任何传出消息。

因此bus.Reply也可以工作。

但是正如我在(1)中所说的,总线实例是完全可重入的,没有必要有多个实例,除非它们实际上是逻辑上不同的端点。

我希望这能回答你的问题。