Use of RabbitMQ under .Net (9) -- Using RabbitMQ under WCF

The RabbitMQ .net client extends WCF with custom Binding and Transport Binding Elements to work over the AMQP protocol. In WCF, Binding, as a stack of Binding Elements, controls most aspects of message transmission such as security, message formats, transactions, and more. The Transport Binding Element in Binding specifies the communication protocol between the server and the client. The Binding provided by the RabbitMQ .net client allows us to use WCF on the AMQP protocol to easily implement common communication methods such as One-Way, Two-Way (Request/Reply), Duplex (Asynchronous Callback), and provide reliable, transactional sexual transmission. We can develop through code and traditional WCF configuration files.

 

ABCs of WCF

Address

The address using RabbitMQ Binding must use the following format: serviceAddress = “soap.amqp:///” serviceName, for example: soap.amqp:///myService. It uses exchange of type direct. Other types of exchanges don't seem to be supported.

It should be noted that it is not recommended to use IIS as the Host, and System.ServiceModel.ServiceHost should be used as the Host, the server of RabbitMQ. The configuration of the address can be configured through code as well as through the config file.

 

Binding

The Binding used by RabbitMQ is not provided in the .net client RabbitMQ.Client, but in a new dll called RabbitMQ.ServiceModel.dll. You can get it from the official website or Nuget. So when referencing RabbitMQ.Client.dll, you should also refer to RabbitMQ.ServiceModel.dll. When defined in the configuration file, the Binding extension must be configured.

We configure as follows in the configuration file:

<bindings>
      <rabbitMQBinding>
        <binding name="rabbitMQConfig"
         protocolversion="AMQP_0_9_1"
                 hostname="localhost"
                 port="5672" />
      </rabbitMQBinding>
    </bindings>
    <extensions>
      <bindingExtensions>
        <add
          name="rabbitMQBinding"
          type="RabbitMQ.ServiceModel.RabbitMQBindingSection, RabbitMQ.ServiceModel, Version=1.0.110.0, Culture=neutral, PublicKeyToken=null"/>
      </bindingExtensions>
    </extensions>

 

For details about Binding in RabbitMQ.ServiceModel.dll, the default and available binding elements can refer to the official documentation.

 

Contract

The definition of Contract is the same as the original WCF definition, there is no difference, just add ServiceContractAttribute and OperationContractAttribute attributes:

[ServiceContract]
public interface ICalculator
{
    [OperationContract]
    int Add ( int x, int y);
    [OperationContract]
    int Subtract(int x, int y);
}

If you want to use Behavior on the implementation of a specific service, it can be the same:

[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerCall)]
public sealed class Calculator : ICalculator
{
    public  int Add ( int x, int y)
    {
        return x + y;
    }
    public  int Subtract ( int x, int y)
    {
        return x - y;
    }
}

 

Serve

The definition of the service is also the same as the commonly used WCF definition, the configuration file definition and the code definition. Host should use System.ServiceModel.ServiceHost. ServiceHost must define a base address or a complete Endpoint address in soap.amqp format. Endpoint must be added using RabbitMQBinding.

service = new ServiceHost(
    typeof(Calculator),
    new Uri("soap.amqp:///"));
service.AddServiceEndpoint(
typeof(ICalculator),
new RabbitMQBinding(
"localhost",
5672,
"guest",
"guest",
"/",
8192,
Protocols.AMQP_0_9_1),
"Calculator");

 

The complete configuration file of the server is defined as follows:

<system.serviceModel>
    <services>
      <service name="ESBTest.WcfRabbitMQ.ConsoleServerPerformance.RabbitMQServer">
        <host>
          <baseAddresses>
            <add baseAddress="soap.amqp:///"   />
          </baseAddresses>
        </host>
        <endpoint
          address="ESBTest.WcfRabbitMQ.ConsoleServerPerformance"
          binding="rabbitMQBinding"
          bindingConfiguration="rabbitMQConfig"
          contract="ESBTest.Contracts.IRequest"/>
      </service>
    </services>
 
    <bindings>
      <rabbitMQBinding>
        <binding name="rabbitMQConfig"
                 hostname="localhost"
                 port="5672"
                 protocolversion="AMQP_0_9_1"
                 oneWay="false"/>
      </rabbitMQBinding>
    </bindings>
 
    <extensions>
      <bindingExtensions>
        <add
          name="rabbitMQBinding"
          type="RabbitMQ.ServiceModel.RabbitMQBindingSection, RabbitMQ.ServiceModel, Version=1.0.110.0, Culture=neutral, PublicKeyToken=null"/>
      </bindingExtensions>
    </extensions>
  </system.serviceModel>

 

Opening multiple servers can also achieve load balancing.

 

client

The definition of the client is also the same as the commonly used WCF definition. The official recommendation is to implement it by inheriting from ClientBase<T> or DuplexClientBase<T>. If it is a Duplex client, InstanceContext must be specified.

The complete client configuration file is defined as follows:

<system.serviceModel>
    <client>
      <endpoint address="soap.amqp:///ESBTest.WcfRabbitMQ.ConsoleServerPerformance"
                binding="rabbitMQBinding"
                bindingConfiguration="rabbitMQConfig"
                contract="ESBTest.Contracts.IRequest"
                name="client" />
    </client>
    <bindings>
      <rabbitMQBinding>
        <binding name="rabbitMQConfig"
         protocolversion="AMQP_0_9_1"
                 hostname="localhost"
                 port="5672" />
      </rabbitMQBinding>
    </bindings>
    <extensions>
      <bindingExtensions>
        <add
          name="rabbitMQBinding"
          type="RabbitMQ.ServiceModel.RabbitMQBindingSection, RabbitMQ.ServiceModel, Version=1.0.110.0, Culture=neutral, PublicKeyToken=null"/>
      </bindingExtensions>
    </extensions>
  </system.serviceModel>

 

We can see that the provided WCF Binding is only some simple and general functions, and some other better functions of RabbitMQ are not provided. Therefore, using WCF or using the client directly depends on the business and system environment. If you only use some simple functions or the entire system is based on WCF, then using WCF for RabbitMQ will provide you with a fast, consistent development model. However, if the scene used is more complex and the performance requirements are relatively high, it is ideal to use the API of the .net client. Comparing directly using the client API and WCF, in terms of speed, WCF takes about 7 times as long as using the API directly, which is much slower. I believe everyone can foresee this.

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=326472884&siteId=291194637