The Publish/Subscribe mode is where the producer sends the message to multiple consumers.
Here are a few key concepts in the Publish/subscribe model-
1. Exchanges (transponder)
Maybe it turns out we're all sending and receiving messages based on a single queue. Now let's look at the complete message delivery pattern.
The core concept of the RABBITMQ message pattern is: The producer does not send any messages directly to the queue . in fact, the producer does not know which queue the message is sent to. instead, producers can only send messages to forwarders .
The forwarder receives the producer's message on the one hand and pushes the message to the queue on the other.
The forwarder must clearly guide how to handle the received message and need to attach the queue? How many are attached? Or is it discarded? These rules are defined by the type of the forwarder. Types are: Direct, Topic, Headers, Fanout.
Here we focus on the last one. Now let's create a fanout type of forwarder, defined as follows:
2. Nameless Exchange (anonymous forwarding)
We may have known nothing about forwarders before, but we can still send messages to the queue, because we used the default forwarder, the forwarder name is an empty string "". The code before we posted the message is:
null, Message.getbytes ());
The first parameter is the name of the forwarder. an empty string represents an anonymous forwarder . The message is routed through the queue's Routingkey to the specified queue.
Now we can specify the name of the forwarder;
null, Message.getbytes ());
3.Temporary queues (Temporary queue)
It is important for us to have a name for the queue when we need to specify the same queue for the consumer.
But sometimes we don't care about the problem, we're only interested in the current flow of news. This time we take the following two steps to resolve:
1) When we connect to RABBITMQ, we need a new empty queue, for which we need to create an empty queue of random names, or better. Let the server choose a random name of the empty queue directly to us.
2) Once the consumer disconnects, the queue is automatically deleted.
Here we provide an queuedeclare () method that creates a non-persisted, standalone, automatically deleted queue with the name randomly generated.
String queuename = Channel.queuedeclare (). Getqueue ();
QueueName is a random queue name.
4.Bindings (binding)
We have created a broadcast repeater and a random queue. Now you need to tell the forwarder to forward the message to the queue. This associated forwarder and queue we call him binding.
Channel.queuebind (QueueName, "Logs", "" ");
This way, the forwarder is attached to the journal queue.
Here is a complete example of a log system:
Send-side code (producer) Emitlog.java
PackageSublog;Importjava.io.IOException;ImportCom.rabbitmq.client.Channel;Importcom.rabbitmq.client.Connection;Importcom.rabbitmq.client.ConnectionFactory; Public classEmitlog {Private Final StaticString exchange_name = "Logs"; Public Static voidMain (string[] args)throwsIOException {/*** Create a connection to connect to MABBITMQ*/ConnectionFactory Factory=NewConnectionFactory (); //set the host IP or host name of the MABBITMQFactory.sethost ("115.159.181.204"); Factory.setport (5672); Factory.setusername ("Admin"); Factory.setpassword ("Admin"); //Create a connectionConnection Connection =factory.newconnection (); //Create a channelChannel Channel =Connection.createchannel (); //Specify forwarding--broadcast((Com.rabbitmq.client.Channel) Channel). Exchangedeclare (Exchange_name, "Fanout"); for(inti=0;i<3;i++){ //the message sentString message = "Hello world!"; ((Com.rabbitmq.client.Channel) Channel). Basicpublish (Exchange_name,"",NULL, Message.getbytes ()); System.out.println ("[x] Sent '" + Message + "'"); } //turn off channels and connectionsChannel.close (); Connection.close (); }}
Consumer 1 Receivelogs2console.java
PackageSublog;Importjava.io.IOException;ImportCom.rabbitmq.client.AMQP;Importcom.rabbitmq.client.AMQP.Connection;ImportCom.rabbitmq.client.Channel;Importcom.rabbitmq.client.ConnectionFactory;ImportCom.rabbitmq.client.Consumer;ImportCom.rabbitmq.client.DefaultConsumer;ImportCom.rabbitmq.client.Envelope; Public classReceivelogs2console {Private Static FinalString exchange_name = "Logs"; Public Static voidMain (string[] argv)throwsIOException, interruptedexception {connectionfactory factory=NewConnectionFactory (); Factory.sethost ("115.159.181.204"); Factory.setport (5672); Factory.setusername ("Admin"); Factory.setpassword ("Admin"); //open Connection and create channel, same as Send endCom.rabbitmq.client.Connection Connection =factory.newconnection (); FinalChannel Channel =Connection.createchannel (); Channel.exchangedeclare (Exchange_name,"Fanout"); //declaring a random queueString QueueName =Channel.queuedeclare (). Getqueue (); Channel.queuebind (QueueName, Exchange_name,""); System.out.println ("[*] waiting for messages. To exit Press CTRL + C "); //Create a queue consumer FinalConsumer Consumer =NewDefaultconsumer (channel) {@Override Public voidHandledelivery (String Consumertag, Envelope Envelope, AMQP. Basicproperties Properties,byte[] body)throwsIOException {String message=NewString (Body, "UTF-8"); System.out.println ("[x] Received '" + Message + "'"); } }; Channel.basicconsume (QueueName,true, consumer); }}
Consumer 2 Receivelogs2file.java
PackageSublog;ImportJava.io.File;Importjava.io.FileNotFoundException;ImportJava.io.FileOutputStream;Importjava.io.IOException;ImportJava.text.SimpleDateFormat;Importjava.util.Date;ImportCom.rabbitmq.client.AMQP;Importcom.rabbitmq.client.AMQP.Connection;ImportCom.rabbitmq.client.Channel;Importcom.rabbitmq.client.ConnectionFactory;ImportCom.rabbitmq.client.Consumer;ImportCom.rabbitmq.client.DefaultConsumer;ImportCom.rabbitmq.client.Envelope; Public classReceivelogs2file {Private Static FinalString exchange_name = "Logs"; Public Static voidMain (string[] argv)throwsIOException, interruptedexception {connectionfactory factory=NewConnectionFactory (); Factory.sethost ("115.159.181.204"); Factory.setport (5672); Factory.setusername ("Admin"); Factory.setpassword ("Admin"); //open Connection and create channel, same as Send endCom.rabbitmq.client.Connection Connection =factory.newconnection (); FinalChannel Channel =Connection.createchannel (); Channel.exchangedeclare (Exchange_name,"Fanout"); //declaring a random queueString QueueName =Channel.queuedeclare (). Getqueue (); Channel.queuebind (QueueName, Exchange_name,""); System.out.println ("[*] waiting for messages. To exit Press CTRL + C "); //Create a queue consumer FinalConsumer Consumer =NewDefaultconsumer (channel) {@Override Public voidHandledelivery (String Consumertag, Envelope Envelope, AMQP. Basicproperties Properties,byte[] body)throwsIOException {String message=NewString (Body, "UTF-8"); Print2file (message);//System.out.println ("[X] Received '" + Message + "'"); } }; Channel.basicconsume (QueueName,true, consumer); } Private Static voidprint2file (String msg) {Try{String dir= Receivelogs2file.class. getClassLoader (). GetResource (""). GetPath (); String LogFileName=NewSimpleDateFormat ("Yyyy-mm-dd"). Format (NewDate ()); File File=NewFile (dir, LogFileName + ". Log"); FileOutputStream Fos=NewFileOutputStream (file,true); Fos.write ((NewSimpleDateFormat ("HH:mm:ss"). Format (NewDate ()) + "-" +msg + "\ r \ n"). GetBytes ()); Fos.flush (); Fos.close (); } Catch(FileNotFoundException e) {e.printstacktrace (); } Catch(IOException e) {e.printstacktrace (); } } }
We used 1 producers to send log messages, 2 consumers, one to print received messages, and another to print the received messages with log information.
The producer declares a broadcast mode converter, and the consumer who subscribes to the converter can receive every message. You can see that there is no declaration queue in the producer. This also validates what was said before. Producers only care about exchange, and it is not the producer's concern as to which queues exchange will forward messages to.
2 consumers, one print log, one write file, except these 2 places are different, the other place is identical. is also a declaration of the broadcast mode of the converter, and the queue is randomly generated, the consumer instance after the launch, will create a random instance, which can be seen in the Management page (). The random queue is also automatically deleted when the instance is closed. Finally, the queue is bound to the forwarder.
Note: Run a 2 consumer instance first, and then run the producer instance. Otherwise, the instance is not obtained.
Rabbitmq/java (Publish/Subscribe mode)