NBear.MQ是NBearFramework中新增的分布式消息队列模块,作为NBear Framework的新成员,NBear.MQ秉承NBear一贯的易于使用和零配置需要的特点,大大改善开发基于消息队列的分布式系统的效率。本文通过介绍一个基于NBear.MQ的Sample - TestServiceMQ,演示基于NBear.MQ开发分布式系统的基本方法。

下载

从SF.NET下载NBear_v1.8.0(包括全部框架及示例源码)
如果你只想先体验一下已编译的示例程序,您也可以从这里下TestServiceMQ_bin.zip 
(请按如下顺序执行bin中的代码:TestRemotingServer.exe, TestServiceHost.exe,TestClientApp.exe,ServiceHost和Client可以是多个,server将自动随机分配调用service的请求到各个service host进行处理)

注:示例程序会使用本机的8000端口,如果本机8000端口已被占用或被禁用,请修改代码以使用其它端口代替或先启用8000端口。

解析

1、TestRemotingServer

首先是我们的Server,对于Server,如果您使用NBear.MQ内置的MemoryServiceMQ,则几乎不需要编码,只需要运行并发布server实例为remoting service。

 1使用NBear.MQ分布式服务消息队列模块开发分布式系统    class Program
 2    }

注意,关键是第8-9行这里,我们调用RemotingServiceHelper类发布MemoryServiceMQ的实例mq到tcp://127.0.0.1:8000/MMQ。

如果你不希望使用MemoryServiceMQ,而希望使用基于其它MQ如MSMQ或ActiveMQ系统的MQ控制,您可以自己实现IServiceMQ接口,用来代替这里的mq。

2、TestServiceHost

Service host顾名思义就是服务的提供者,本示例的TestServiceHost定义了两个service,MathService和HelloWorldService,如下:

 1使用NBear.MQ分布式服务消息队列模块开发分布式系统    public class MathService : BaseAutoService
 2    }

大家可以看到,这里的service都是从BaseAutoService继承的,您也可以实现IService或继承BaseService。一个可以被NBear.MQ使用的Service基本上做的事情就是接受一个RequestMessage类型的输入参数,返回一个ResponseMessage类型的返回结果。

RequestMessage和ResponseMessage都从Message类型继承,除了包含请求和返回相关的一组参数(.net基本数据类型),每个Message包含Text、Bytes和Data属性,分别允许存放和传递string,byte[]和Dataset类型的数据。可见Message实际是一个比较通用的DTO。

下面,我们要将示例service注册到server,这个过程可以非常方便的通过SimpleServiceContainer来实现:

 1使用NBear.MQ分布式服务消息队列模块开发分布式系统    class Program
 2    }

您可以看到,我们首先要通过RemotingClientHelper类获得我们的server发布出来的mq实例。然后,创建一个SimpleServiceContainer实例,并将我们的示例service添加到container,就这么简单。SimpleSeviceContainer会自动为我们注册和绑定service和mq,您也可以注册多个相同和不同类型的service到container。

3、TestClientApp

Client是一个WinForm程序,自然就是调用Service了。代码如下:

  1使用NBear.MQ分布式服务消息队列模块开发分布式系统using System;
  2使用NBear.MQ分布式服务消息队列模块开发分布式系统using System.Collections.Generic;
  3使用NBear.MQ分布式服务消息队列模块开发分布式系统using System.ComponentModel;
  4使用NBear.MQ分布式服务消息队列模块开发分布式系统using System.Data;
  5使用NBear.MQ分布式服务消息队列模块开发分布式系统using System.Drawing;
  6使用NBear.MQ分布式服务消息队列模块开发分布式系统using System.Text;
  7使用NBear.MQ分布式服务消息队列模块开发分布式系统using System.Windows.Forms;
  8使用NBear.MQ分布式服务消息队列模块开发分布式系统
  9使用NBear.MQ分布式服务消息队列模块开发分布式系统using NBear.MQ.ServiceMQ;
 10使用NBear.MQ分布式服务消息队列模块开发分布式系统using NBear.MQ;
 11使用NBear.MQ分布式服务消息队列模块开发分布式系统using NBear.Common;
 12使用NBear.MQ分布式服务消息队列模块开发分布式系统using NBear.Common.Remoting;
 13使用NBear.MQ分布式服务消息队列模块开发分布式系统
 14使用NBear.MQ分布式服务消息队列模块开发分布式系统namespace TestClientApp
 15}

Line 23-31  在Form Load是初始化container,这和service host是完全一样的。

调用service只需通过container.CallService方法,如Line 82 和 105。

问题

1、您可能会问,client的代码除了调用service和service host的代码几乎相同,那么是否可以在client中既使用service又提供service呢 ?当然可以,你也完全可以在client这里register service,当client调用一个service时,container会首先检查是否存在本地service,存在则调用本地,不存在则向server请求远程service。

2、本示例是在一台服务器上演示这个分布式构架,您也可以修改地址,并分别把server, service host和client部署到互相连接的多台server上。

运行

请按如下顺序执行bin中的代码:TestRemotingServer.exe, TestServiceHost.exe,TestClientApp.exe,ServiceHost和Client可以是多个,server将自动随机分配调用service的请求到各个service host进行处理。在运行过程中,请尝试多次点击client的按钮,并观察,server和service host的日志,看是不是负载均衡。您也可以尝试在运行过程中关闭某些service host或client,或者再新增一些,注意server会自动维护service host和client的绑定和回调。

致谢

NBear.MQ很多地方参考了alex兄的QPG分布式构架,并得到了alex兄的许多指点,在此表示最高的谢意!

相关文章: