"4" Publish and subscribe

Source: Internet
Author: User
Tags amq

In the previous section we created a task queue and assumed that the work queues would distribute each task accurately to a worker. In this chapter we will create a more complex example – we will distribute a message to multiple consumers. This mode is publish/subscribe.
To illustrate this pattern, we will build a simple log system. It contains two programs – the first is used to issue log messages, and the second receives and prints them.
In our log system, each receiver that is running will receive a message. This allows us to receive messages from one receiver and log them directly to the disk, and we can run another receiver to print the logs on the screen.
In essence, log messages are distributed to all receivers by broadcast.

Exchanges
In the previous chapters, we used a queue to send and receive messages. And now we're going to cover the RABBITMQ message model completely.
First, let's review the previous example:

    • Producer: The application used to send messages

    • Queues: buffers that store messages

    • Consumer: An application used to consume messages

The core idea of the RABBITMQ message model is that producers do not send messages directly to the queue. In fact, the producer simply does not know whether the message was sent to any queue.
Instead, the producer can only send messages to the exchanger Exchange (hereafter referred to as the exchanger). The switch principle is very simple, on the one hand it receives the message from the producer and on the other hand pushes the message to the message queue. The exchanger must know how to handle every message that is received. Is it added directly to a specific queue? or add to multiple queues? or discard it directly. How messages are handled depends on the type of exchanger.

The types of exchangers are: direct, topic, headers and fanout. This chapter focuses on the fourth type: Fanout. Let's create a switch of that type and name it logs:

Channel.exchangedeclare ("Logs", "fanout");

The fanout exchanger is very simple. As you might guess by name, it's a queue that broadcasts all incoming messages to its know. This is exactly what our logger needs.

Exchanger LIST
We can execute the command rabbitmqctl to list the server's exchanger lists:

$ sudo rabbitmqctl list_exchanges
Listing exchanges ...
Direct
Amq.direct Direct
Amq.fanout fanout
Amq.headers headers
Amq.match headers
Amq.rabbitmq.log Topic
Amq.rabbitmq.trace Topic
Amq.topic Topic
Logs Fanout
... done

There are switches in the list that start with amq.* and the unnamed (default) switches, which are created by default, but you are unlikely to use them.

Unknown switch
In the previous example we did not use any switches, but we can still send messages to the queue. This is because we have used the default switch by setting the string named "".
Look back at the way we sent the message:

Channel.basicpublish ("", "Hello", NULL, Message.getbytes ());

The first parameter is the name of the exchanger. An empty string indicates the use of the default or nameless switch: The message is routed to the queue specified by Routingkey.

We can send a message to our named exchanger using the following code:

Channel.basicpublish ("Logs", "", NULL, Message.getbytes ());

Temporary queue
Do you still remember the specified named queue we used in the previous example? such as Hello and task_queue. When you want to share a queue between producers and consumers, it is important to name the queue.
But the logger for our example does not need this. We want to collect all the log information and not a subset of them. We are only interested in the current message of influenza and will not pay attention to the old news. To achieve this example, we need to do two things.
First, whenever we connect to RABBITMQ, we all need a new, empty queue. How to do? We can create a queue with a random name or let the server choose a randomly named queue, which is better.
The second thing is that once our consumers are connected, the queue should be automatically deleted.
In the Java client, we can call the Queuedeclare () method without a parameter to create a non-persistent, proprietary, automatically deleted queue; The method returns the name of the queue.

String queuename = Channel.queuedeclare (). Getqueue ();

The content of the variable queuename is the random name of the queue, similar to the string ' Amq.gen-jzty20brgko-hjmujj0wlg '.

Bindings

We have created a fanout type of exchanger and a queue. Now we can tell the exchanger to send a message to the queue. The relationship between the exchanger and the queue is called binding.

Channel.queuebind (QueueName, "Logs", "" ");

Now the logs exchanger will append the message to the queue we created.

Bindings List
We can use the command rabbitmqctl list_bindings to list all the bindings.

Execute code

The producer code used to send the log messages looks no different from the previous. The more important change is that we send the message to a switch named logs instead of the system's default, nameless switch. We need to provide a routingkey when sending a message, but the fanout type of exchanger ignores the value. Here's the full code:

import com.rabbitmq.client.connectionfactory;import com.rabbitmq.client.connection;import  Com.rabbitmq.client.channel;public class emitlog {  private static final  String EXCHANGE_NAME =  "Logs";   public static void main (string[] &NBSP;ARGV)  throws exception {    connectionfactory factory =  new connectionfactory ();     factory.sethost ("localhost");     connection connection = factory.newconnection ();    channel  Channel = connection.createchannel ();     channel.exchangedeclare (EXCHANGE_NAME,   "Fanout");     string message = getmessage (argv);     channel.basicpublish (exchange_name,  "",  null, message.getbytes ());     system.out.println (" [x]&nbsP sent  ' " + message + " ");     channel.close ();     connection.close ();   }    private static string getmessage ( string[] strings) {    if  (strings.length < 1)          return  "info: hello world!";     return joinstrings (strings,  " ");  }     Private static string joinstrings (String[] strings, string delimiter)  {     int length = strings.length;    if  (length  == 0)  return  ";    stringbuilder words = new  StringBuilder (Strings[0]);    for  (int i = 1; i <  length; i++)  {         words.append (delimiter). Append (Strings[i]);     }    return  words.tostring ();   }}

As you can see, after the connection is established, we create a fanout exchanger, which is a step that must be made. Suppresses the sending of messages to a non-existent exchanger.
If there is no queue bound to this switch, then the message sent will be lost, but this has little effect in our example. we can safely discard messages if there is no consumer listening to the message queue. The complete Receivelogs.java code for
is as follows:

import com.rabbitmq.client.connectionfactory;import com.rabbitmq.client.connection;import  com.rabbitmq.client.channel;import com.rabbitmq.client.queueingconsumer;public class  receivelogs {  private static final string exchange_name =  "Logs" ;   public static void main (STRING[]&NBSP;ARGV)  throws exception {     connectionfactory factory = new connectionfactory ();     factory.sethost ("localhost");    connection connection =  Factory.newconnection ();     channel channel = connection.createchannel ();     channel.exchangedeclare (exchange_name,  "fanout");     string  queuename = channel.queuedeclare (). Getqueue ();     channel.queuebind ( queuename, exchange_name,  "");  &nBsp;      system.out.println (" [*] waiting for messages.  to exit press ctrl+c ");     queueingconsumer consumer =  new queueingconsumer (channel);     channel.basicconsume (QueueName, true,  consumer);    while  (True)  {       Queueingconsumer.delivery delivery = consumer.nextdelivery ();       string message = new string (Delivery.getbody ());       System.out.println (" [x] Received " " + message + " ");        }  }}


"4" Publish and subscribe

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.