IWantToRunWhenBusStartsAndStops 不用于生产?

IWantToRunWhenBusStartsAndStops not for production?

NServiceBus (4.7.5) 的新功能,刚刚实现了一个 NSB host.exe 托管服务(实现 IWantToRunWhenBusStartsAndStops),它检测数据库表的更改并通过发布事件通知订阅 Web 应用程序,例如"CustomerDataWasUpdatedEvent"。显然,将来我们将通过接收命令的消息处理程序执行实际更新,但目前此发布服务只是轮询数据库等。

一切正常,但是,在临近生产时,我注意到 David Boike 在他最新一期的 "Learning NServiceBus" 中指出 类 实施 IWantToRunWhenBusStartsAndStops 实际上主要用于开发,很少用于生产。我在 Start 方法中设置了我的数据库更改检测,它运行良好,有人知道为什么不鼓励这样做吗?

以下为真书评论:

https://books.google.se/books?id=rvpzBgAAQBAJ&pg=PA110&lpg=PA110&dq=nservicebus+iwanttorunwhenbusstartsandstops+in+production+david+boike&source=bl&ots=U6sNII0nm3&sig=qIXffOVFhcy-_3qDnSExRpwRlD4&hl=sv&sa=X&ei=lHWRVc2_BKrWywPB65fIBw&ved=0CBsQ6AEwAA#v=onepage&q=nservicebus%20iwanttorunwhenbusstartsandstops%20in%20production%20david%20boike&f=false

实际报价为:

...it isn't common to have widespread use of in a production system.

不常见与气馁不是一回事。

也就是说,我确实认为作者在这里有意强调这样一个事实,即在页面的更上方,他们断言这不是进行大量编码的好地方,因为未处理的异常可能会导致整个页面过程失败。

作者实际上确实继续提到了一个可能的用例,当您可能想要加载资源以在处理程序中工作时。

Ok, maybe it's just this scenario we have that is a bit uncommon

同意 - 您的方法从根本上没有错。我最近和你做了同样的事情,连接 SqlDependency 来监听数据库事件,然后发布一条消息作为结果。在这些情况下,除了使用 IWantToRunAtStatup 之外,您几乎无能为力。

此外,David 本人经常浏览 nservicebus 标签,也许他会提供比我更明确的答案。

我将复制我在 Particular Software Google Group...

中给出的答案

我在这里直接引用自己的话:

An implementation of IWantToRunWhenBusStartsAndStops is a great place to create a quick interface in order to test messages during debugging by allowing you to send messages based on the console input. Apart from this, it isn't common to have widespread use of them in a production system. One possible production use case will be to provision a resource needed by the endpoint at startup and then tear it down when the endpoint stops.

我想如果我能稍微强调一下,那就是 "widespread use"。我并不是想说您不会在生产代码中使用 IWantToRunWhenBusStartsAndStops 或避免使用它们是最佳做法。t/can我想说的是,拥有大量它们可能是一种代码味道。

在本书的该段之上,我警告 IWantToRunWhenBusStartsAndStops 没有任何环境事务或 try/catch 正在进行的事情。这真的是关键部分。如果您最终在 IWantToRunWhenBusStartsAndStops 中抛出异常,您可能 运行 陷入大问题。如果您使用类似 .NET Timer 的东西然后抛出异常,您可能会使您的进程崩溃!

让我告诉你我是如何在我的第一个 NServiceBus 系统中搞砸的。该系统(据我所知,至今仍在使用)负责将 3000 多个 RSS 提要(可能比现在多得多)摄取到 CMS 中。所以处理每个提要,将其分解为项目,调整图像大小,为移动设备编码附加视频......所有这些事情都在 NServiceBus 消息处理程序中处理,它被扩展到多个服务器,这一切都很棒。

问题出在调度程序上。我将其实现为 IWantToRunWhenBusStartsAndStops(好吧,当时实际上是 IWantToRunAtStartup),它很快就变得一团糟。我将整个 table 的提要信息保存在内存中,以便我可以计算何时触发下一个 ProcessFeed 命令。我使用的是 .NET Timer class 和 IIRC,我最终不得不使用像 ManualResetEvent 这样的线程原语来协调 activity。而且因为我使用的是 .NET Timer,如果调度程序抛出异常,该端点将失败并且必须重新启动。很多奇怪的边缘情况,它总是一个错误的泥潭。另外,这现在是一个单例 "commander app",所以虽然 feed/item 处理器可以横向扩展,但调度程序不能。

随着我对 NServiceBus 的经验越来越丰富,我意识到每个提要都应该是一个传奇,从一个 FeedCreated 事件开始,通过 PauseProcessing 和 ResumeProcessing 命令控制,使用超时来控制下一个处理时间,最后(也许) 通过 FeedRemoved 事件结束。这会更直接,一切都会在事务控制的消息处理程序中执行。

那次经历让我有点 distrustful/skeptical IWantToRunWhenBusStartsAndStops。并不是说它不好,只是需要注意一些事情。随时准备考虑是否无法通过其他方式更好地完成您正在尝试做的事情。