rabbitmq4--after the post-forget and RPC

Source: Internet
Author: User
Tags rabbitmq

Introducing RABBITMQ into a project usually takes into account the benefits it brings: decoupling the application, implementing interoperability between different programming languages, releasing reliance on a particular communication protocol, and releasing the application's dependency on timing (asynchronous). The implementation to the code level is two common application patterns: "After the hair is forgotten" ( fire-and-forget) and RPC.

Fire-and-forget RabbitMQ solves the problem of interconnection between applications (connect) and size (scale), message sending and receiving is isolated, the sender does not know who is ultimately receiving the message, and the receiver does not have to care about who the message was sent from, and the sending and receiving is isolated , the message is inherently asynchronous. This isolation also decouples dependencies between applications. The role of RABBITMQ is the router in the middle of the application. This is a "post-and-forget" (Fire-and_forget) way to publish a message. RPC RPC requires two-way communication, or RPC server needs to know exactly who to send the message to. We can attach the endpoint information "to whom" in the payload data section. RABBITMQ provides a solution: There is a reply_to field on each AMQP message header. This allows the producer of the message to specify that the queue Name,rpc server accept the message check reply_to field, Create a message that contains response and put the queue name as routing key, and the client subscribing to the queue gets the message.

Here are two things to make sure:

    1. To create a random name for a queue
    2. Even if name is a random conflict, it is also necessary to guarantee the exclusivity of the message traffic.

See how RABBITMQ satisfies these two points:

    1. If you create a queue that does not specify queue NAME,RABBITMQ, a random name is created.
    2. Exclusive only requires exclusive parameters

All in all, what needs to be done is to create a Temporary,exclusive,anonymou queue for the client and set the queue name to the Reply_to field of the RPC message. Note here RPC The server already knows which queue to post to, so there's no need to specify exchange (we'll mention the difference between queue and exchange at the implementation level, and simply say that the queue will have a corresponding Erlang process. And Exchang just performs some pattern matching checks and does not correspond to process entities). See:

Our RPC would work like this:

    • When the Client is starts up, it creates a anonymous exclusive callback queue.
    • For a RPC request, the Client sends a message with the properties: ReplyTo, which are set to the callback queue and correlationid, which is set to a unique value for every request.
    • The request is a sent to an rpc_queue queue.
    • The RPC Worker (Aka:server) is a waiting for requests on this queue. When a request appears, it does the job and sends a message with the result of the to the Client, using the C4>replyto field.
    • The client waits for data on the callback queue. When a-message appears, it checks the Correlationid property. If it matches the value from the request it returns the response to the application

The code for the RPC client side is as follows:

Importcom.rabbitmq.client.ConnectionFactory;Importcom.rabbitmq.client.Connection;ImportCom.rabbitmq.client.Channel;ImportCom.rabbitmq.client.QueueingConsumer;Importcom.rabbitmq.client.AMQP.BasicProperties;ImportJava.util.UUID; Public classrpcclient {PrivateConnection Connection; Privatechannel Channel; PrivateString requestqueuename = "Rpc_queue"; PrivateString Replyqueuename; PrivateQueueingconsumer Consumer;  PublicRpcclient ()throwsException {connectionfactory Factory=NewConnectionFactory (); Factory.sethost ("LocalHost"); Connection=factory.newconnection (); Channel=Connection.createchannel (); Replyqueuename=Channel.queuedeclare (). Getqueue (); Consumer=NewQueueingconsumer (channel); Channel.basicconsume (Replyqueuename,true, consumer); }   PublicString call (String message)throwsException {String response=NULL; String Corrid=Uuid.randomuuid (). toString (); Basicproperties Props=Newbasicproperties.                                Builder (). Correlationid (Corrid). ReplyTo (Replyqueuename)    . build (); Channel.basicpublish ("", Requestqueuename, props, Message.getbytes ("UTF-8"));  while(true) {queueingconsumer.delivery Delivery=Consumer.nextdelivery (); if(Delivery.getproperties (). Getcorrelationid (). Equals (Corrid)) {Response=NewString (Delivery.getbody (), "UTF-8");  Break; }    }    returnresponse; }   Public voidClose ()throwsException {connection.close (); }   Public Static voidMain (string[] argv) {rpcclient Fibonaccirpc=NULL; String Response=NULL; Try{Fibonaccirpc=Newrpcclient (); System.out.println ("[x] requesting FIB (30)"); Response= Fibonaccirpc.call ("30"); System.out.println (" [.] Got ' "+ Response +" ' "); }    Catch(Exception e) {e.printstacktrace (); }    finally {      if(fibonaccirpc!=NULL) {        Try{fibonaccirpc.close (); }        Catch(Exception ignore) {}}} }}
View Code

The RPC sever port code is as follows:

Importcom.rabbitmq.client.ConnectionFactory;Importcom.rabbitmq.client.Connection;ImportCom.rabbitmq.client.Channel;ImportCom.rabbitmq.client.QueueingConsumer;Importcom.rabbitmq.client.AMQP.BasicProperties; Public classRpcserver {Private Static FinalString rpc_queue_name = "Rpc_queue"; //calculating the Fibonacci Pocena sequence    Private Static intFibintN) {if(n = = 0)            return0; if(n = = 1)            return1; returnFIB (n-1) + fib (n-2); }     Public Static voidMain (string[] argv) {Connection Connection=NULL; Channel Channel=NULL; Try{ConnectionFactory Factory=NewConnectionFactory (); Factory.sethost ("LocalHost"); Connection=factory.newconnection (); Channel=Connection.createchannel (); Channel.queuedeclare (Rpc_queue_name,false,false,false,NULL); Channel.basicqos (1); Queueingconsumer Consumer=NewQueueingconsumer (channel); Channel.basicconsume (Rpc_queue_name,false, consumer); System.out.println ("[x] awaiting RPC requests");  while(true) {String response=NULL; Queueingconsumer.delivery Delivery=Consumer.nextdelivery (); Basicproperties Props=delivery.getproperties (); Basicproperties Replyprops=NewBasicproperties.builder (). Correlationid (Props.getcorrelationid ()). build (); Try{String message=NewString (Delivery.getbody (), "UTF-8"); intn =integer.parseint (message); System.out.println (" [.] FIB ("+ Message +") "); Response= "" +fib (n); } Catch(Exception e) {System.out.println (" [.] " +e.tostring ()); Response= ""; } finally{channel.basicpublish ("", Props.getreplyto (), Replyprops, Response.getbytes ("UTF-8")); Channel.basicack (Delivery.getenvelope (). Getdeliverytag (),false); }            }        } Catch(Exception e) {e.printstacktrace (); } finally {            if(Connection! =NULL) {                Try{connection.close (); } Catch(Exception ignore) {}}} }}
View Code

Slightly different

The traditional RPC call client and server are tightly dependent, clients connect to the server, send a request, and then block waiting for the server to respond. This is done with the client and server side being aware of each other. If the RPC server crashes, the client needs to reconnect, If the server is completely blown up, look for a server that provides the same service, and the client will reconnect to the past.

Using RABBITMQ to implement RPC, still maintain the characteristics of client server information hiding, client relies on not a specific server but a specific message, in the case of multiple equivalent servers, Whether the state of a server is normal does not affect the state of the client.

Summing up, the use of RABBITMQ is the first RPC, objectively also achieve the following effect:

    1. Fault tolerance a server crash does not affect the Client
    2. Decoupling the dependency on specific communication protocols and interfaces, and unifying the AMQP messages.
    3. Load balancing between multiple RPC servers is done by RABBITMQ

rabbitmq4--after the post-forget and RPC

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.