ASP.NET应用程序能否处理NServiceBus事件



大多数(如果不是全部的话)ASP.NET(或MVC)的NSB示例都让web应用程序使用Bus.Send发送消息,并可能注册一个简单的回调,这基本上就是我在应用程序中使用它的方式。

我想知道的是,在同一个ASP.NET应用程序中处理消息是否可能和/或是否有意义。

我问的主要原因是缓存。这个过程可能是这样的:

  1. 用户从web应用程序启动请求
  2. Web应用程序向独立的应用程序服务器发送消息,并将更改记录在本地数据库中
  3. 在同一用户将来的页面请求中,web应用程序会意识到更改,并将其列为"挂起"状态
  4. 后端会发生很多事情,最终请求会被批准或拒绝。将发布引用原始请求的事件
  5. 此时,web应用程序应该开始显示最新信息

现在,在一个真正的网络应用程序中,几乎可以肯定的是,这个挂起的请求将被缓存,很可能会被缓存很长一段时间,因为否则,每当用户请求当前信息时,应用程序都必须查询数据库中的挂起更改

因此,当请求最终在后端完成时(这可能需要一分钟或一天的时间),web应用程序至少需要使该缓存条目无效,并进行另一次DB查找。

现在我意识到这可以用SqlDependency对象等进行管理,但让我们假设它们不可用——也许它不是SQL Server后端,或者可能当前的信息查询进入了web服务,不管怎样。问题是,网络应用程序是如何意识到状态的变化的?

如果可以在ASP.NET应用程序中处理NServiceBus消息,那么处理程序的上下文是什么?换句话说,IoC容器将不得不注入一堆依赖项,但它们的作用域是什么?这一切都是在HTTP请求的上下文中执行的吗?或者消息处理程序的所有内容都需要是静态/单例的吗?

有没有更好/推荐的方法来解决这类问题?

我自己也在想同样的事情——web应用程序与NServiceBus基础设施的适当耦合级别是多少?在我的领域中,我有一个类似的问题需要解决,涉及使用SignalR代替缓存。和你一样,我也没有找到很多关于这个特定模式的文档。然而,我认为有可能推理一下遵循它的一些含义,然后决定它在你的环境中是否有意义。

简而言之,我认为让web应用程序订阅NServiceBus事件是完全可能的。我不认为会有任何技术障碍,尽管我必须承认我实际上并没有尝试过——如果你有时间的话,一定要试一试。我只是有一种强烈的感觉,如果一个开始需要来做这件事,那么可能会有一个更好的整体设计等待发现。以下是我认为情况如此的原因:

  1. 要问的一个相关问题与您的缓存实现有关。如果它是一个分布式或集中式模型(比如SQL、MongoDB、Memcached等),那么@Adam Fyles建议的方法听起来是个好主意。您不需要通知每个web应用程序-更新缓存可以由一个NServiceBus端点完成,该端点不是web应用程序的部分。换句话说,web应用程序的每个实例和"缓存更新"端点都将访问相同的共享缓存。然而,如果你的缓存是进程中的,就像微软的Web缓存一样,那么你当然要解决一个更棘手的问题,除非你能像建议的那样依靠最终一致性
  2. 如果您的web应用程序订阅了特定的NServiceBus事件,那么您就有必要为web应用程序的每个实例创建一个唯一的输入队列。由于最好的做法是考虑使用负载均衡器扩展您的网络应用程序,这意味着您最终可能会有N个队列和至少N个订阅,这比恒定数量的订阅更令人担忧。再说一遍,这不是技术上的障碍,只是一些会让我惊讶的事情
  3. 链接到David Boike的文章提出了一个有趣的观点,即应用程序池以及它们的寿命可能如何不确定。此外,如果您在服务器上为同一应用程序同时运行多个应用程序池(这是一种常见的情况),它们都将尝试从同一消息队列中读取,并且没有很好的方法来确定哪一个将实际处理消息。更多的是那样,这将很重要。相比之下,根据Udi Dahan的这篇文章,发送命令不需要输入队列。这就是为什么我认为网络应用程序发送的单向命令在实践中更常见
  4. 关于单一责任原则,这里有很多话要说。总的来说,我想说的是,如果您能够尽可能多地将发送和接收消息的"专业技能"委派给NServiceBus主机,那么您的整体体系结构将更干净、更易于管理。通过经验,我发现,如果我把我的网络农场视为一个单一的实体,即去掉对单个网络服务器身份的所有确认,我往往就不用担心了。让每个web服务器都成为总线上的端点有点打破了这一概念,因为现在"哪个服务器"又以消息队列的形式出现了

这有助于澄清问题吗?

可以创建一个端点(NSB)来订阅发布的事件并更新缓存。在进行实际更新之前,不应发布该事件,这样您就不会失去同步。网络应用程序会在下一次请求时继续从缓存中提取数据,或者你可以构建某种延迟。

最新更新