RABBITMQ use encapsulation for the. NET Platform

Source: Internet
Author: User

Objective

RABBITMQ We are all familiar with this article, however, this post mainly RABBITMQ a share of rabbitmq.client after learning about the package. At the end of the article, I'll put the package components and demos on.

The operation of RABBITMQ

As you can see, the publisher (publisher) sends the message first to the exchanger (Exchange), then from the exchanger to the specified queue, and has previously declared that the exchanger is bound to the queue, and the consumer (customer) subscribes to or actively take the specified queue messages for consumption.

Then just mentioned the subscription and active fetch can be understood as, push (passive), pull (active).

Push, as long as the queue adds a message, the idle consumer is notified of the consumption. (I'm not looking for you, just wait for you to find me, observer mode)

Pull, will not inform the consumer, but by the consumer actively round or timed to pick up the queue message. (I need to find you)

Using the scene I would like to give an example, if there are two systems order system and delivery system, from the order system to initiate delivery message orders, in order to timely delivery, the delivery system needs to subscribe to the queue, as long as there are instructions to deal with.

However, the program occasionally abnormal, such as the network or DB timeout, the message dropped to the failure queue, this time requires a re-send mechanism. But I do not want while (ispostsuccess = = True), because as long as the exception, there will be an exception in a certain period of time, such a retry is meaningless.

This time does not need to deal with the message in a timely manner, there is a job timed or every few minutes (the number of failures * interval minutes) to take the failure queue messages, to re-send.

Publish (Release) package

Step: Initialize link, declaration exchanger, declaration queue, change machine and queue bindings, publish messages. Note that I saved the model in Concurrentdictionary because it is time-consuming to declare and bind, and secondly, sending messages to a repeating queue does not need to be reinitialized.

 1//<summary> 2///Switch Declaration 3//</summary> 4//<param name= "IModel"  ;</param> 5//<param name= "Exchange" > Switch </param> 6//<param name= "type" > Exchanger type: 7///1, Direct exchange– handles routing keys. A queue needs to be bound to the switch, requiring the message to match exactly 8////For a particular routing key. This is a complete match. If a queue is bound to the switch requiring the routing key "Dog", then only 9///messages marked as "dog" are forwarded, Dog.puppy will not be forwarded, Dog.guard will not be forwarded, only DOG10///2, Fanout E will be forwarded. xchange– does not handle routing keys. You simply have to bind the queue to the switch. A message sent to the switch is 11//or forwarded to all queues that are bound to the switch. Much like a subnet broadcast, each host in the network receives a copy of the message. FANOUT12///switch forwarding message is the fastest. 13///3, Topic exchange– to match the routing key with a pattern. At this point the queue needs to be bound to a pattern. The symbol "#" matches one or more 14 or more words, and the symbol "*" matches not many more than one word. So "audit.#" can match to "audit.irs.corporate", but "audit.*" 15///will only match to "Audit.irs". &LT;/PARAM&GT;16//<param name= "durable" > Persistent </param>17//<param name= "Autodelete" > Auto     Delete </param>18//<param name= "Arguments" > Parameters </param>19    private static void Exchangedeclare (IModel IModel, String Exchange, String type = exchangetype.direct,20 b OOL durable = true,21 bool Autodelete = False, idictionary<string, object> arguments = null) 22 { Exchange = Exchange. Isnullorwhitespace ()? "": Exchange.  Trim (); Imodel.exchangedeclare (Exchange, type, durable, autodelete, arguments); 25}26 27// &LT;SUMMARY&GT;28///</summary>30//<param name= "channel" ></param&gt         ///<param name= "queue" > Queue </param>32///<param Name= "durable" > Persistent </param>33 <param name= "Exclusive" > exclusive queue, if a queue is declared as an exclusive queue, the queue is only visible to the connection that first declares it, 34///and automatically deleted when the connection is broken. Here are three points to note: First, the exclusive queue is visible based on the connection, and the different channels of the same connection are 35///To access the exclusive queue created by the same connection at the same time. Second, "For the first time", if a connection has declared an exclusive queue, the other 36////is not allowed to establish an exclusive queue of the same name, which is different from the normal queue. Third, even if the queue is persisted, once the connection is closed or 37///client exits, the exclusive queue will be automatically deleted. This queue applies to only one client sendingThe scenario in which the message was read. </param>38//<param name= "Autodelete" > Automatically delete </param>39//<param name= "arguments" ; parameter </param>40 private static void Queuedeclare (IModel channel, string queue, bool durable = TRUE, bool Exclu             sive = false,41 bool Autodelete = False, idictionary<string, object> arguments = null) 42 {43 Queue = queue. Isnullorwhitespace ()? "Undefinedqueuename": Queue. Trim ();  Queuedeclare (queue, durable, exclusive, autodelete, arguments);}46///<summary>48// Get Model49//</summary>50//<param name= "Exchange" > Switch name </param>51//<p Aram name= "queue" > Queue name </param>52//<param name= "Routingkey" ></param>53//<para  M name= "isproperties" > whether persistent </param>54//<returns></returns>55 private static IModel Getmodel (String exchange, StriNg queue, String routingkey, bool isproperties = False), (queue, key =&gt , and the _conn var model =. Createmodel (); Exchangedeclare (model, Exchange, Exchangetype.fanout, isproperties); Qu Euedeclare (model, queue, isproperties), model.             Queuebind (queue, Exchange, Routingkey), modeldic[queue] = model;64 return model;65 });}67//<summary>69///</summary>71///&L T;param name= "Routingkey" > Routing key </param>72//<param name= "Body" > Queue information </param>73//&LT ;p Aram name= Exchange > Switch name </param>74//<param name= "queue" > Queue name </param>75//< param name= "isproperties" > whether persistent </param>76//<returns></returns>77 public void Publi SH (string exchange, String qUeue, String Routingkey, string body, bool Isproperties = false) (+) + var channel = Getmodel (Exchange , queue, Routingkey, isproperties), try82. Basicpublish (Exchange, Routingkey, NULL, body. SerializeUtf8 ());}85 catch (Exception ex). Getinnestexception (); 88}89}

View Code

The next time this is a native test, the publishing speed:

4.2W/S belongs to a steady speed, and the deserialization (ToJson) is slightly faster.

Subscribe (subscription) package

The release is the declaration of the switch and queue and binding, however, the subscription only need to declare the queue. As can be seen from the code below, when the exception is caught, the message is sent to a custom "dead-letter queue", which is timed to be re-sent by another job, so finally is a successful answer.

        <summary>///Get model//</summary>/<param name= "queue" > Queue name </p aram>//<param name= "isproperties" ></param>///<returns></returns> Priv Ate static IModel Getmodel (string queue, bool Isproperties = False) {return Modeldic.getoradd (queue, VA Lue = {var model = _conn.                 Createmodel ();                 Queuedeclare (model, queue, isproperties); The number of messages per consumption model.                 Basicqos (0, 1, false);                 Modeldic[queue] = model;             return model;        }); }///<summary>//Receive messages///</summary>//<typeparam name= "T" ></typ eparam>//<param name= "queue" > Queue name </param>//<param name= "Isproperties" ></param&        Gt <param name= "Handler" > Consumer processing </param>//<param name= "isDeAdletter "></param> public void subscribe<t> (string queue, bool isproperties, action<t> Handler            , bool Isdeadletter) where T:class {//queue declaration var channel = Getmodel (queue, isproperties);            var consumer = new Eventingbasicconsumer (channel); Consumer. Received + = (model, ea) = {var BODY = ea.                Body; var msgStr = body.                DeserializeUtf8 ();                var msg = msgstr.fromjson<t> ();                try {handler (msg); } catch (Exception ex) {ex. Getinnestexception ().                    WriteToFile ("Queue Receive Message", "RabbitMq");                if (!isdeadletter) publishtodead<deadletterqueue> (queue, MSGSTR, ex); } finally {channel. Basicack (ea.                Deliverytag, false);           }            }; Channel.        Basicconsume (queue, false, consumer); }

View Code

The next time this is a native test, the publishing speed:

There are 1.9k/s when you are fast, and 1.7k/s when you are slow.

Pulling (pull) package

Directly on the code:

        <summary>///Get news///</summary>//<typeparam name= "T" ></typepara m>//<param name= "Exchange" ></param>///<param name= "queue" ></param>// /<param name= "Routingkey" ></param>///<param Name= "handler" > Consumer processing </param> Private V            OID poll<t> (String Exchange, String queue, String Routingkey, action<t> handler) where T:class {            var channel = Getmodel (Exchange, queue, Routingkey); var result = Channel.            Basicget (queue, false); if (result.            IsNull ()) return; var msg = result. Body.deserializeutf8 ().            Fromjson<t> ();            try {handler (msg); } catch (Exception ex) {ex. Getinnestexception ().            WriteToFile ("Queue Receive Message", "RabbitMq"); } finally {channel. Basicack (resUlt.            Deliverytag, false); }        }

View Code

There's 1.8k/s, stability is 1.5k/s.

Encapsulation of RPC (remote invocation)

First of all, RABBITMQ just provides the functionality of this RPC, but not the real RPC, why do you say:

1, traditional RPC hides the invocation details, such as calling local methods to pass parameters, throwing exceptions

2, RABBITMQ RPC is message-based, consumer consumption, the response results are returned through the new queue.

        <summary>//RPC client///</summary>//<param name= "Exchange" ></par        am>//<param name= "queue" ></param>///<param name= "Routingkey" ></param> <param name= "Body" ></param>//<param name= "isproperties" ></param>//<ret Urns></returns> public string Rpcclient (string Exchange, String queue, String Routingkey, string body, Boo            L Isproperties = false) {var channel = Getmodel (Exchange, queue, Routingkey, isproperties);            var consumer = new Queueingbasicconsumer (channel); Channel.            Basicconsume (queue, true, consumer); try {var correlationid = Guid.NewGuid ().                ToString (); var basicproperties = Channel.                Createbasicproperties ();                Basicproperties.replyto = queue;              Basicproperties.correlationid = Correlationid;  Channel. Basicpublish (Exchange, Routingkey, Basicproperties, body.                SerializeUtf8 ());                var sw = stopwatch.startnew (); while (true) {var ea = consumer.                    Queue.dequeue (); if (ea. Basicproperties.correlationid = = Correlationid) {return ea.                    Body.deserializeutf8 (); } if (SW.                Elapsedmilliseconds > 30000) throw new Exception ("Wait for Response timeout"); }} catch (Exception ex) {throw ex.            Getinnestexception (); }}///<summary>//RPC Server///</summary>//<typeparam name= "T" & gt;</typeparam>//<param name= "Exchange" ></param>///<param name= "queue" ></par am>//<param name= "isproperties" ></param>//<param name= "Handler" ></param>//<param name= "Isdeadletter" ></param> public void rpcservice<t> (string Exchan GE, string queue, bool isproperties, func<t, t> handler, bool Isdeadletter) {//Queue declaration VA            R channel = Getmodel (queue, isproperties);            var consumer = new Eventingbasicconsumer (channel); Consumer. Received + = (model, ea) = {var BODY = ea.                Body; var msgStr = body.                DeserializeUtf8 ();                var msg = msgstr.fromjson<t> (); var props = ea.                Basicproperties; var replyprops = Channel.                Createbasicproperties (); Replyprops.correlationid = props.                Correlationid;                try {msg = handler (msg); } catch (Exception ex) {ex. Getinnestexception ().                WriteToFile ("Queue Receive Message", "RabbitMq");           } finally     {Channel. Basicpublish (Exchange, props. ReplyTo, Replyprops, MSG. ToJson ().                    SerializeUtf8 ()); Channel. Basicack (ea.                Deliverytag, false);            }            }; Channel.        Basicconsume (queue, false, consumer); }

View Code

Can be used, but not recommended to use. Other RPC frameworks can be considered. GRPC, thrift and so on.

End

This article, there is not too much to write RABBITMQ knowledge points, because the garden of learning notes is too much. Here's my code on the http://www.php.cn/. If there is a problem with finding the wrong place in the comments, I will revise it in time to avoid misleading others.

If this article is useful to you, please click on the recommendation, thank you for reading.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.