.Net下RabbitMQ的使用(9) — 在WCF下使用RabbitMQ

释放双眼,带上耳机,听听看~!

RabbitMQ .net客户端通过自定义的Binding和Transport Binding Element扩展了WCF,使之能够在AMQP协议上使用。在WCF中,Binding作为一系列Binding Elements的栈,控制了消息传输的大部分方面如安全,消息格式,事务等等。而Binding中的Transport Binding Element传输绑定元素,则指定了服务端和客户端之间的通信协议。RabbitMQ .net客户端提供的Binding使我们可以在AMQP协议上面使用WCF方便的实现One-Way, Two-Way(Request/Reply),Duplex(Asynchronous Callback)这样的常见通信方式,并且提供可靠的,事务性的传输。我们可以通过代码和传统WCF配置文件的方式进行开发。

 

WCF的ABC

Address

使用RabbitMQ Binding 的地址一定要使用如下格式:serviceAddress = “soap.amqp:///” serviceName,例如:soap.amqp:///myService。它使用类型是direct的exchange。其他类型的exchange似乎不被支持。

需要注意的是,用IIS来作为Host是不被推荐的,应该使用System.ServiceModel.ServiceHost来Host,RabbitMQ的服务端。地址的配置可以通过代码也同样可以通过config文件来配置。

 

Binding

RabbitMQ使用的Binding不是在.net客户端RabbitMQ.Client中提供,而是在RabbitMQ.ServiceModel.dll这个新的dll中提供。可以再官方网站或者Nuget中获取到。所以在引用RabbitMQ.Client.dll的同时还要引用RabbitMQ.ServiceModel.dll。在配置文件中定义时,必须要配置Binding的extension。

我们在配置文件中如下配置:


1
2
1<bindings>
2

1
2
1      <rabbitMQBinding>
2

1
2
1        <binding name="rabbitMQConfig"
2

1
2
1         protocolversion="AMQP_0_9_1"
2

1
2
1                 hostname="localhost"
2

1
2
1                 port="5672" />
2

1
2
1      </rabbitMQBinding>
2

1
2
1    </bindings>
2

1
2
1    <extensions>
2

1
2
1      <bindingExtensions>
2

1
2
1        <add
2

1
2
1          name="rabbitMQBinding"
2

1
2
1          type="RabbitMQ.ServiceModel.RabbitMQBindingSection, RabbitMQ.ServiceModel, Version=1.0.110.0, Culture=neutral, PublicKeyToken=null"/>
2

1
2
1      </bindingExtensions>
2

1
2
1    </extensions>
2

 

关于RabbitMQ.ServiceModel.dll中Binding的相关详细信息,默认使用和可以使用的绑定元素可以参考官方提供的文档。

 

Contract

Contract的定义是和原来的WCF定义是一样的,没有什么区别,加上ServiceContractAttribute和OperationContractAttribute属性就可以:


1
2
1[ServiceContract]
2

1
2
1public interface ICalculator
2

1
2
1{
2

1
2
1    [OperationContract]
2

1
2
1    int Add(int x, int y);
2

1
2
1    [OperationContract]
2

1
2
1    int Subtract(int x, int y);
2

1
2
1}
2

如果要在具体服务的实现上使用Behavior也可原来一样:


1
2
1[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
2

1
2
1public sealed class Calculator : ICalculator
2

1
2
1{
2

1
2
1    public int Add(int x, int y)
2

1
2
1    {
2

1
2
1        return x + y;
2

1
2
1    }
2

1
2
1    public int Subtract(int x, int y)
2

1
2
1    {
2

1
2
1        return x - y;
2

1
2
1    }
2

1
2
1}
2

 

服务

服务的定义也和常用的WCF定义一样,配置文件定义和代码定义。Host应该使用System.ServiceModel.ServiceHost。ServiceHost必须定义一个基地址或者是完整的Endpoint地址,该地址是用soap.amqp格式的。Endpoint必须添加使用RabbitMQBinding。


1
2
1service = new ServiceHost(
2

1
2
1    typeof(Calculator),
2

1
2
1    new Uri("soap.amqp:///"));
2

1
2
1service.AddServiceEndpoint(
2

1
2
1typeof(ICalculator),
2

1
2
1new RabbitMQBinding(
2

1
2
1"localhost",
2

1
2
15672,
2

1
2
1"guest",
2

1
2
1"guest",
2

1
2
1"/",
2

1
2
18192,
2

1
2
1Protocols.AMQP_0_9_1),
2

1
2
1"Calculator");
2

 

服务端完整的配置文件定义如下:


1
2
1<system.serviceModel>
2

1
2
1    <services>
2

1
2
1      <service name="ESBTest.WcfRabbitMQ.ConsoleServerPerformance.RabbitMQServer">
2

1
2
1        <host>
2

1
2
1          <baseAddresses>
2

1
2
1            <add baseAddress="soap.amqp:///"   />
2

1
2
1          </baseAddresses>
2

1
2
1        </host>
2

1
2
1        <endpoint
2

1
2
1          address="ESBTest.WcfRabbitMQ.ConsoleServerPerformance"
2

1
2
1          binding="rabbitMQBinding"
2

1
2
1          bindingConfiguration="rabbitMQConfig"
2

1
2
1          contract="ESBTest.Contracts.IRequest"/>
2

1
2
1      </service>
2

1
2
1    </services>
2

1
2

2

1
2
1    <bindings>
2

1
2
1      <rabbitMQBinding>
2

1
2
1        <binding name="rabbitMQConfig"
2

1
2
1                 hostname="localhost"
2

1
2
1                 port="5672"
2

1
2
1                 protocolversion="AMQP_0_9_1"
2

1
2
1                 oneWay="false"/>
2

1
2
1      </rabbitMQBinding>
2

1
2
1    </bindings>
2

1
2

2

1
2
1    <extensions>
2

1
2
1      <bindingExtensions>
2

1
2
1        <add
2

1
2
1          name="rabbitMQBinding"
2

1
2
1          type="RabbitMQ.ServiceModel.RabbitMQBindingSection, RabbitMQ.ServiceModel, Version=1.0.110.0, Culture=neutral, PublicKeyToken=null"/>
2

1
2
1      </bindingExtensions>
2

1
2
1    </extensions>
2

1
2
1  </system.serviceModel>
2

 

开多个服务端,同样可以实现负载均衡。

 

客户端

客户端的定义也和常用的WCF定义一样,官方推荐通过继承自ClientBase<T>或DuplexClientBase<T>来实现。如果是Duplex的客户端,InstanceContext必须要指定的。

完整的客户端配置文件定义如下:


1
2
1&lt;system.serviceModel&gt;
2

1
2
1    &lt;client&gt;
2

1
2
1      &lt;endpoint address=&quot;soap.amqp:///ESBTest.WcfRabbitMQ.ConsoleServerPerformance&quot;
2

1
2
1                binding=&quot;rabbitMQBinding&quot;
2

1
2
1                bindingConfiguration=&quot;rabbitMQConfig&quot;
2

1
2
1                contract=&quot;ESBTest.Contracts.IRequest&quot;
2

1
2
1                name=&quot;client&quot; /&gt;
2

1
2
1    &lt;/client&gt;
2

1
2
1    &lt;bindings&gt;
2

1
2
1      &lt;rabbitMQBinding&gt;
2

1
2
1        &lt;binding name=&quot;rabbitMQConfig&quot;
2

1
2
1         protocolversion=&quot;AMQP_0_9_1&quot;
2

1
2
1                 hostname=&quot;localhost&quot;
2

1
2
1                 port=&quot;5672&quot; /&gt;
2

1
2
1      &lt;/rabbitMQBinding&gt;
2

1
2
1    &lt;/bindings&gt;
2

1
2
1    &lt;extensions&gt;
2

1
2
1      &lt;bindingExtensions&gt;
2

1
2
1        &lt;add
2

1
2
1          name=&quot;rabbitMQBinding&quot;
2

1
2
1          type=&quot;RabbitMQ.ServiceModel.RabbitMQBindingSection, RabbitMQ.ServiceModel, Version=1.0.110.0, Culture=neutral, PublicKeyToken=null&quot;/&gt;
2

1
2
1      &lt;/bindingExtensions&gt;
2

1
2
1    &lt;/extensions&gt;
2

1
2
1  &lt;/system.serviceModel&gt;
2

 

我们可以看到,提供的WCF Binding只是一些简单通用的功能,RabbitMQ的一些其他比较好的功能并没有提供。所以使用WCF或者直接使用客户端要视业务和系统环境而定,如果只是使用一些简单的功能或整个系统都是基于WCF的,那么使用WCF来做RabbitMQ,会给你提供一个快速的,一致性的开发模型。但如果使用的场景比较复杂,性能要求比较高的话还是使用.net客户端的API比较理想。直接使用客户端API和WCF来比较,就速度而言,WCF花的是时间大概是直接使用API的7倍左右,慢得多。这点相信大家也是可以预见的。

给TA打赏
共{{data.count}}人
人已打赏
安全网络

CDN安全市场到2022年价值76.3亿美元

2018-2-1 18:02:50

安全运维

SpringBoot+Mysql+Redis+RabbitMQ实现高并发秒杀

2021-12-11 11:36:11

个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索