HTML5技术

使用NServiceBus开发分布式应用 - richiezhang(2)

字号+ 作者:H5之家 来源:博客园 2015-12-15 08:04 我要评论( )

为了处理GreetingCommand,新建一个GreetingHandler.cs的类,只需要继承IHandleMessagesGreetingCommand即可表明该类会处理类型为GreetingCommand的消息。 public class GreetingHandler:IHandleMessagesGreetingCo

为了处理GreetingCommand,新建一个GreetingHandler.cs的类,只需要继承IHandleMessages<GreetingCommand>即可表明该类会处理类型为GreetingCommand的消息。

public class GreetingHandler:IHandleMessages<GreetingCommand> { private readonly IBus _bus; public GreetingHandler(IBus bus) { _bus = bus; } public void Handle(GreetingCommand message) { Console.WriteLine("Received greetingCommand:{0}, times:{1}, Hello world",message.Id,message.Times); _bus.Publish(new GreetingEvent(){Id = message.Id,Times = message.Times}); } }

方法public void Handle(GreetingCommand message)描述了当收到GreetingCommand消息会输出了字符串Hello World。另外代码最后发布了一个类型为GreetingEvent的事件,所有对此事件感兴趣的订阅者都可以订阅此事件。在NServiceBus中发布一个事件采用bus.Publish<TEvent>(TEvent event)方法。你会注意到我们通过构造器注入的方式来获取bus实例。

也许你会很关心此服务端中的配置文件如何配置呢?此服务端收到了别的程序发送的消息,具体谁发送的他并不知情。另外发布了一个事件,但是具体谁来订阅该事件,作为事件的发布者并不知道,所以该项目的消息路由配置为空:

<MessageEndpointMappings></MessageEndpointMappings>

7、截至目前,我们已经完成了显示hello world的任务,让我们运行起来看看吧:

在项目配置中将NBus.Practice.GreetingClient和NBus.Practice.GreetingServer同时设置为启动项。CTRL+F5

运行结果:当我们在客户端中按"Enter"键,服务端会收到消息并输出“Hello World”。

此时如果我们关闭服务端,并在客户端中多敲几次回车键发送GreetingCommand消息会怎么样?让我么来模拟真实场景下服务端应用由于未知原因宕机,会出现什么情况呢?

此时如果我们打开MSMQ管理工具就会发现服务端未处理的消息存储在队列中,直到服务端再次上线重新处理这些消息,从而保证了分布式应用中数据的最终一致性。

8、刚才服务端处理完GreetingCommand并发布了GreetingEvent事件,我们接下来新建一个类型为Console Application的事件订阅者:NBus.Practice.GreetingSubscriber。

事件订阅者跟之前一样需要创建并启动一个bus。

9、新建一个Congratulation.cs来处理GreetingEvent消息:

public class Congratulation:IHandleMessages<GreetingEvent> { public void Handle(GreetingEvent message) { Console.WriteLine("Received greeting event id:{0}, time{1}, congratulations, you have learned NServiceBus.",message.Id,message.Times); } }

10、订阅者的消息路由如何配置?

<MessageEndpointMappings> <add Messages="NBus.Practice.GreetingMessage" Endpoint="Nbus.Practice.HelloWorld.Server" /> </MessageEndpointMappings>

这句配置的含义是:订阅EndPoint为Nbus.Practice.HelloWorld.Server且消息定义在程序集为NBus.Practice.GreetingMessage中的消息。

由此可见根据程序的角色不同,配置文件的配置具有不同的含义。

11、在事件的发布/订阅模式中,订阅者可以是一个或多个,我们将新建第二个订阅者来展示此功能。新建一个类型为Class library的程序集: NBus.Practice.GreetingAnotherSubscriber。

这次的程序之所以要换成Class library是因为我们本次要使用NServiceBus.Host来Host此程序。

Install-Package NServiceBus.Host

NServiceBus会为项目自动添加一个EndpointConfig.cs文件,我们将在此文件中配置bus:

public class EndpointConfig : IConfigureThisEndpoint { public void Customize(BusConfiguration configuration) { configuration.EndpointName("Nbus.Practice.HelloWorld.AnotherSubscriber"); configuration.UseSerialization<JsonSerializer>(); configuration.UsePersistence<InMemoryPersistence>(); } }

同时添加一个Handler来处理GreetingEvent消息。

public class GreetingLogger:IHandleMessages<GreetingEvent> { public void Handle(GreetingEvent message) { Console.WriteLine("Received greeting event id:{0}, time{1}, I will log it.",message.Id,message.Times); } }

通过下面的方式使用NServiceBus.Host.exe来Host本程序。

11、    最后把本教程中建立的四个程序全都跑起来看看效果:

四、总结

本文通过一个简单的实例展示了如何在服务总线中发送命令,如何使用发布/订阅基本思想来实现一个Hello world。这个例子很简单,但是隐隐之中展现了CQRS的基本思想:Client发送一个Command,DomainHandler收到Command后会调用Domain逻辑,此时Domain会发布领域事件,Query分支会订阅领域事件来更新Query数据库,同时还有缓存、搜索引擎、其他服务也会订阅此领域事件。各个服务之间构成了松耦合的分布式应用程序。

当然NServiceBus还有更多高级主题例如:持久化、Saga、单元测试、二级重试、依赖注入、负载均衡、更换消息队列等内容等着我们去一探究竟。

整个例子的代码:https://git.oschina.net/richieyangs/NServiceBusPractice,以后会将所有NServiceBus相关的例子放在这个项目中。

 

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  • 【Vue 入门】使用 Vue2 开发一个展示项目列表的应用 - zhangjk

    【Vue 入门】使用 Vue2 开发一个展示项目列表的应用 - zhangjk

    2017-04-30 16:00

  • 对于Bootstrap的介绍以及如何使用 - novai-L

    对于Bootstrap的介绍以及如何使用 - novai-L

    2017-04-29 09:00

  • 在Delphi下使用迅雷APlayer组件进行免注册开发 - Delphi力量

    在Delphi下使用迅雷APlayer组件进行免注册开发 - Delphi力量

    2017-04-28 15:00

  • 探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 构建记事本应用 - nzbin

    探索 vuex 2.0 以及使用 vuejs 2.0 + vuex 2.0 构建记事本应用 - nzb

    2017-04-25 09:02

网友点评
t