Introduction, installation and use of RabbitMQ

RabbitMQ RabbitMQ 1.MQ introduction 2. Use scenario 2.1. Peak shaving The origin of peak shaving 2.2 log processing 2...
1.MQ introduction
2. Use scenario
3. Introduction to rabbitmq
4. AMQP agreement
5. Single node installation in Windows Environment
6. Use of rabbitmq management interface
7.RabbitMQ message type
Message response and message persistence
Exchange (switch forwarder)

RabbitMQ

RabbitMQ

1.MQ introduction

MQ is called Message Queue. Message Queue (MQ) is an application to application communication method.

2. Use scenario

2.1. Peak shaving

The origin of flow peak shaving

It mainly comes from the business scenarios of the Internet, for example, the Spring Festival train ticket rush to start soon, a large number of users need to rush to buy at the same time; and the well-known Alibaba double 11 seconds kill, In a short time, hundreds of millions of users swarmed in, and the instantaneous flow was huge (high concurrency). For example, 2 million people were ready to rush to buy a product at 12:00 in the morning, but the number of products was limited to about 100-500.

In this way, there are only a few hundred users who can actually buy this product. But in terms of business, seckill hopes more people to participate in it, that is to say, more and more people are expected to come to see and buy the product before rush buying.

However, when the time of rush to buy is up and the user starts to place an order, the lack of back-end server of seckill doesn't want millions of people to launch rush to buy at the same time.

We all know that the processing resources of the server are limited, so when there is a peak, it is easy to cause server downtime and users can not access the situation.

2.2 log processing

2.3 Application decoupling

2.4 asynchronous processing

3. Introduction to rabbitmq

Introduction

RabbitMQ, developed in Erlang, is an open-source message middleware that implements AMQP advanced message queuing protocol.

Advantages:

  • Very good performance, low latency
  • Throughput to 10000
  • Good management interface management tools
  • The community is relatively active

Disadvantages:

  • Relatively low throughput

4. AMQP agreement

Advanced Message Queuing Protocol

5. Single node installation in Windows Environment

Download the installation package

Click to jump to download RabbitMQ page

View the Erlang version required for this RabbitMQ

Download erlang

To install erlang:

Double click the default installation and select the installation directory. The directory cannot have Chinese characters, and the computer name cannot have Chinese characters

Configure erlang environment variables

Open cmd input erl

Install rabbitmq

Activate the rabbitMQ UI management interface:

Run in the sbin directory of rabbit

D:\work\java\rabbitMQ\rabbitmq_server-3.8.3\sbin> rabbitmq-plugins.bat enable rabbitmq_management

Restart service:

Browser access: http://localhost:15672/
Enter username: guest
input password:guest

6. Use of rabbitmq management interface

Browser address bar input: localhost:15672

User name: guest password: Guest

Add user

​ Tags

Admin: Super Administrator

Monitoring: monitor, which can view node information

Policymaker: policy maker (mirror)

​ Management:

​ Impersonator:

​ None

Added an admin password 123456, Tags: Administrator

Add Virtual Host

Virtual Host is equivalent to mysql db

Add: usually starts with "/"


After adding:

to grant authorization:

Set admin to access vhost01

Click user name

Select Virtual Host and Set permission

7.RabbitMQ message type

7.1 simple queue

P: Message producer

Red: queue

C: Consumers

Three objects: producer queue consumer

7.1.1 get ConnectionUtil:
import com.rabbitmq.client.Connection; import com.rabbitmq.client.ConnectionFactory; public class ConnectionUtil { /** * Get MQ connection * @return */ public static Connection getConnection() throws IOException, TimeoutException { // Define a connection factory ConnectionFactory factory = new ConnectionFactory(); // Set service address factory.setHost("localhost"); // AMQP 5672 factory.setPort(5672); // vhost factory.setVirtualHost("/vhost01"); // user name factory.setUsername("admin"); // password factory.setPassword("123456"); return factory.newConnection(); } }
7.1.2 message producer: Send
public class Send { private static final String QUERE_NAME="test_simple_queue"; public static void main(String[] args) throws IOException, TimeoutException { // Get a connection Connection connection = ConnectionUtil.getConnection(); // Get a channel from the connection Channel channel = connection.createChannel(); // Declare a queue channel.queueDeclare(QUERE_NAME, false, false, false, null); String message = "hello simple !"; channel.basicPublish("", QUERE_NAME, null, message.getBytes()); System.out.println("send message"); channel.close(); connection.close(); } }
7.1.3 consumer: Recv
public class Recv { private static final String QUERE_NAME="test_simple_queue"; public static void main(String[] args) throws IOException, TimeoutException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Create channel Channel channel = connection.createChannel(); // Queue declaration channel.queueDeclare(QUERE_NAME, false, false,false, null); // Define consumers for the queue DefaultConsumer defaultConsumer = new DefaultConsumer(channel){ // Get arrival message @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body); String msgString = new String(body,"utf-8"); System.out.println("new api recv: " + msgString); } }; // listen queue channel.basicConsume(QUERE_NAME, true, defaultConsumer); } }
7.1.4 disadvantages of simple queues:

The coupling is high. The producer corresponds to the consumer one by one (if I want to have multiple messages in the consumer consumption queue, this is not the case). When the queue name is changed, it must be changed at the same time

7.2 work queues, fair distribution polling distribution

7.2.1 why the work queue appears:

simple queues are one-to-one correspondence, and in our actual development, it is effortless for producers to send messages, while consumers generally need to integrate with business. Consumers need to process after receiving messages, which may take time. At this time, there will be a lot of messages in the queues

7.2.2 distribute polling 7.2.2.1 message producer: Send
public class Send { public static final String QUEUE_NAME = "test_work_queue"; /** * |--> C2 * P ---> Queue ----| * |--> C1 * @param args * @throws IOException * @throws TimeoutException */ public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false, null); // send message for (int i = 0; i < 50; i++) { String msg= "send hello " + i; channel.basicPublish("", QUEUE_NAME, null, msg.getBytes()); System.out.println("[WQ] send msg = " + msg); Thread.sleep(i*20); } // close resource channel.close(); connection.close(); } }
7.2.2.2 consumer: Recv1:
public class Recv1 { public static final String QUEUE_NAME = "test_work_queue"; public static void main(String[] args) throws IOException, TimeoutException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false,null); // Define a consumer Consumer consumer = new DefaultConsumer(channel) { // Message arrival, trigger this method @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { //super.handleDelivery(consumerTag, envelope, properties, body); String msg = new String(body, "utf-8"); System.out.println("Recv [1] msg = " + msg); try{ Thread.sleep(2000); }catch (InterruptedException e) { e.printStackTrace(); }finally{ System.out.println("Recv [1] done!"); } } }; // listen queue boolean autoAck = true; channel.basicConsume(QUEUE_NAME, autoAck, consumer); } }
7.2.2.3 consumer: Recv2
public class Recv2 { public static final String QUEUE_NAME = "test_work_queue"; public static void main(String[] args) throws IOException, TimeoutException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false,null); // Define a consumer DefaultConsumer defaultConsumer = new DefaultConsumer(channel) { // Message arrival, trigger this method @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body); String msg = new String(body, "utf-8"); System.out.println("Recv [2] msg = " + msg); try{ Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally{ System.out.println("Recv [2] done!"); } } }; // listen queue boolean autoAck = true; channel.basicConsume(QUEUE_NAME, autoAck, defaultConsumer); } }
7.2.2.4 phenomenon:

Consumer 1 and consumer 2 handle the same number of messages

Consumer 1: even
Consumer 2: odd
This method is called round robin, and the result is that no matter who is busy or who is idle, no more messages will be sent. The task is always one for you and one for me

7.2.3 fair dispatch

Manual receipt required

// MQ sends only one request to the consumer at a time. When the consumer finishes processing the message, it will manually receive the receipt, and then MQ sends another message to the consumer channel.basicQos(1); boolean autoAck = false; //false manual receipt, after processing the message, tell MQ channel.basicConsume(QUEUE_NAME, autoAck, defaultConsumer);
7.2.3.1 producers
public class Send { public static final String QUEUE_NAME = "test_work_queue"; /** * |--> C2 * P ---> Queue ----| * |--> C1 * @param args * @throws IOException * @throws TimeoutException */ public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false, null); /** * Before each consumer sends a confirmation message, the message queue does not send the next message to the consumer, and only processes one message at a time * Limit sending more than one message to the same consumer */ channel.basicQos(1); // send message for (int i = 0; i < 50; i++) { String msg= "send hello " + i; channel.basicPublish("", QUEUE_NAME, null, msg.getBytes()); System.out.println("[WQ] send msg = " + msg); Thread.sleep(i*5); } // close resource channel.close(); connection.close(); } }
7.2.3.2 consumer 1
public class Recv1 { public static final String QUEUE_NAME = "test_work_queue"; public static void main(String[] args) throws IOException, TimeoutException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false,null); // MQ sends only one request to the consumer at a time. When the consumer finishes processing the message, it will manually receive the receipt, and then MQ sends another message to the consumer channel.basicQos(1); // Define a consumer Consumer consumer = new DefaultConsumer(channel) { // Message arrival, trigger this method @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { //super.handleDelivery(consumerTag, envelope, properties, body); String msg = new String(body, "utf-8"); System.out.println("Recv [1] msg = " + msg); try{ Thread.sleep(2000); }catch (InterruptedException e) { e.printStackTrace(); }finally{ System.out.println("Recv [1] done!"); // Manual receipt channel.basicAck(envelope.getDeliveryTag(), false); } } }; // listen queue // boolean autoAck = true; / / auto answer boolean autoAck = false; //Manual response channel.basicConsume(QUEUE_NAME, autoAck, consumer); } }
7.2.3.3 consumers 2
public class Recv2 { public static final String QUEUE_NAME = "test_work_queue"; public static void main(String[] args) throws IOException, TimeoutException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false,null); // MQ sends only one request to the consumer at a time. When the consumer finishes processing the message, it will manually receive the receipt, and then MQ sends another message to the consumer channel.basicQos(1); // Define a consumer DefaultConsumer defaultConsumer = new DefaultConsumer(channel) { // Message arrival, trigger this method @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { super.handleDelivery(consumerTag, envelope, properties, body); String msg = new String(body, "utf-8"); System.out.println("Recv [2] msg = " + msg); try{ Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally{ System.out.println("Recv [2] done!"); // Manual receipt channel.basicAck(envelope.getDeliveryTag(), false); } } }; // listen queue boolean autoAck = false; //false manual receipt channel.basicConsume(QUEUE_NAME, autoAck, defaultConsumer); } }
7.2.3.4 phenomenon:

Consumer 2 processes more messages than consumer 1, and has more to offer

7.3 publish/subscribe


1. One producer, multiple consumers
2. Each consumer has its own queue
3. The producer does not send the message directly to the queue, but to the exchange converter exchange
4. Each queue must be bound to the switch
5. The message sent by the producer passes through the switch and reaches the queue. Can realize a message to be consumed by multiple consumers

producer
public class Send { public static final String EXCHANGE_NAME = "test_exchange_fanout"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); // Claim switch channel.exchangeDeclare(EXCHANGE_NAME, "fanout"); //distribute // send message String msg = "hello ps"; channel.basicPublish(EXCHANGE_NAME, "", null, msg.getBytes()); System.out.println("Send msg = " + msg); channel.close(); connection.close(); } }

Where's the news?? Lost, because the switch does not have the storage capacity, in rabbitmq only the queue has the storage capacity.
Because there is no queue bound to the switch after declaring the switch, the data is lost

Registration - "email -" SMS "

Consumer 1: Recv1
public class Recv1 { public static final String QUEUE_NAME = "test_queue_fanout_email"; public static final String EXCHANGE_NAME = "test_exchange_fanout"; public static void main(String[] args) throws IOException, TimeoutException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false,null); // Ensure that only one is distributed at a time channel.basicQos(1); // Bind to switch forwarder channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ""); // Define a consumer Consumer consumer = new DefaultConsumer(channel) { // Message arrival, trigger this method @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { //super.handleDelivery(consumerTag, envelope, properties, body); String msg = new String(body, "utf-8"); System.out.println("Recv [1] msg = " + msg); try{ Thread.sleep(2000); }catch (InterruptedException e) { e.printStackTrace(); }finally{ System.out.println("Recv [1] done!"); // Manual receipt channel.basicAck(envelope.getDeliveryTag(), false); } } }; // listen queue boolean autoAck = false; channel.basicConsume(QUEUE_NAME, autoAck, consumer); } }
Consumer 2: Recv2
public class Recv2 { public static final String QUEUE_NAME = "test_queue_fanout_sms"; public static final String EXCHANGE_NAME = "test_exchange_fanout"; public static void main(String[] args) throws IOException, TimeoutException { // Get connection Connection connection = ConnectionUtil.getConnection(); // Get channel Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false,null); // Bind to switch forwarder channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, ""); // Ensure that only one is distributed at a time channel.basicQos(1); // Define a consumer Consumer consumer = new DefaultConsumer(channel) { // Message arrival, trigger this method @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { //super.handleDelivery(consumerTag, envelope, properties, body); String msg = new String(body, "utf-8"); System.out.println("Recv [2] msg = " + msg); try{ Thread.sleep(2000); }catch (InterruptedException e) { e.printStackTrace(); }finally{ System.out.println("Recv [2] done!"); // Manual receipt channel.basicAck(envelope.getDeliveryTag(), false); } } }; // listen queue boolean autoAck = false; channel.basicConsume(QUEUE_NAME, autoAck, consumer); } }

7.4. Routing wildcard mode

producer
public class Send { public static final String EXCHANGE_NAME = "test_exchange_direct"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); // exchange channel.exchangeDeclare(EXCHANGE_NAME, "direct"); String msg = "hello direct !"; // routing key String routingKey = "info"; channel.basicPublish(EXCHANGE_NAME, routingKey, null, msg.getBytes()); System.out.println("send :" + msg); channel.close(); connection.close(); } }
Consumer 1: Recv1
public class Recv1 { public static final String EXCHANGE_NAME = "test_exchange_direct"; public static final String QUEUE_NAME = "test_queue_direct_1"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); // Declaration queue channel.queueDeclare(QUEUE_NAME, false, false, false,null); // Bind queue to switch and routingKey channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error"); // Ensure that only one is distributed at a time channel.basicQos(1); // Define a consumer Consumer consumer = new DefaultConsumer(channel){ // Message arrival, trigger this method @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String msg = new String(body, "utf-8"); System.out.println("Recv [1] msg = " + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally{ // Message receipt channel.basicAck(envelope.getDeliveryTag(), false); System.out.println("Recv [1] done!"); } } }; // Listen to queue autoack: false manual receipt (message receipt channel.basicAck(envelope.getDeliveryTag(), false);) channel.basicConsume(QUEUE_NAME, false, consumer); } }
Consumer 2: Recv2
public class Recv2 { public static final String EXCHANGE_NAME = "test_exchange_direct"; public static final String QUEUE_NAME = "test_queue_direct_2"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false,null); channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "error"); channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "info"); channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "waring"); channel.basicQos(1); Consumer consumer = new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String msg = new String(body, "utf-8"); System.out.println("Recv [2] msg = " + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally{ channel.basicAck(envelope.getDeliveryTag(), false); System.out.println("Recv [2] done!"); } } }; channel.basicConsume(QUEUE_NAME, false, consumer); } }

7.5.Topics

​ Topic exchange
Match route to a pattern
To match one or more characters
* match one character
For example: Goods#

Products: publish, delete, modify, query

producer

public class Send { public static final String EXCHANGE_NAME = "test_exchange_topic"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); // Claim switch channel.exchangeDeclare(EXCHANGE_NAME, "topic"); String message = "commodity..."; channel.basicPublish(EXCHANGE_NAME, "goods.delete", null, message.getBytes()); System.out.println("send message = " + message); channel.close(); connection.close(); } }

consumer:

public class Recv1 { public static final String EXCHANGE_NAME = "test_exchange_topic"; public static final String QUEUE_NAME = "test_queue_topic_1"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false,false,false,null); //Binding: channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "goods.add"); channel.basicQos(1); //Defining consumers Consumer consumer = new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String msg = new String(body, "utf-8"); System.out.println("[1] recv msg: " + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally{ System.out.println("[1] recv done!"); // Manual receipt channel.basicAck(envelope.getDeliveryTag(), false); } } }; // listen queue channel.basicConsume(QUEUE_NAME, false, consumer); } }

Consumer 2

public class Recv2 { public static final String EXCHANGE_NAME = "test_exchange_topic"; public static final String QUEUE_NAME = "test_queue_topic_2"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false,false,false,null); //Binding: channel.queueBind(QUEUE_NAME, EXCHANGE_NAME, "goods.#"); channel.basicQos(1); //Defining consumers Consumer consumer = new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String msg = new String(body, "utf-8"); System.out.println("[2] recv msg: " + msg); try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } finally{ System.out.println("[2] recv done!"); // Manual receipt channel.basicAck(envelope.getDeliveryTag(), false); } } }; // listen queue channel.basicConsume(QUEUE_NAME, false, consumer); } }

7.6 RPC manual and automatic message acknowledgment (message acknowledgment mechanism transaction - confirm)

In rabbitmq, we can solve the problem of abnormal data loss of rabbitmq server by persisting data
Question: after the producer sends the message, whether the message has arrived at the rabbitmq server or not is unknown by default
There are two ways:

AMQP implements transaction mechanism

confirm mode

Transaction mechanism:

txSelect txCommit txRollback

txSelect: the user sets the current channel to transaction mode
txCommit: used to commit transactions
txRollback: rollback transaction

producer
public class TxSend { public static final String QUEUE_NAME = "test_queue_tx"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); String msg = "hello tx message"; try{ // Open transaction channel.txSelect(); channel.basicPublish("", QUEUE_NAME, null, msg.getBytes()); System.out.println(1/0); //Commit transaction channel.txCommit(); } catch(Exception e){ // Rollback transaction channel.txRollback(); System.out.println("send message txRollback"); } finally{ channel.close(); connection.close(); } }

consumer:

public class TxRecv { public static final String QUEUE_NAME="test_queue_tx"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); channel.basicConsume(QUEUE_NAME, true, new DefaultConsumer(channel){ @Override public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body) throws IOException { String msg = new String(body, "utf-8"); System.out.println("recv[tx] msg:" + msg); } }); } }

This mode is still time-consuming, which reduces the message throughput of Rabbitmq

Confirm mode

Implementation principle of producer mode

The producer sets the channel to confirm mode. Once the channel enters confirm mode, all messages published on the channel will be assigned a unique ID (starting from 1). Once the message is delivered to all matching queues, the broker sends an acknowledgement to the producer (containing the unique ID of the message). This enables the producer to know that the message has arrived at the destination queue correctly. If the message and queue are persistent, the acknowledgement message will be sent after the message is written to the disk. The delivery tag field of the acknowledgement message returned by the broker to the producer contains the serial number of the acknowledgement message. In addition, the broker can also set the basic.ack The multiple domain of. Indicates that all messages before this serial number have been processed.

The biggest advantage of Confirm mode is that it is asynchronous

Nack

Turn on confirm mode
channel.confirmSelect();

Programming mode:

1. General waitForCOnfirms()

  1. Send a batch of waitForConfirms in batch
  2. Asynchronous confirm mode: provides a callback

General confirm single general

send

/** * Normal mode */ public class Send1 { public static final String QUEUE_NAME = "test_queue_confirm1"; public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // The producer calls confirm select to set chancel to confirm mode. Note (an exception will occur if the transaction mechanism is changed to this) channel.confirmSelect(); String msg = "hello confirm message"; channel.basicPublish("", QUEUE_NAME, null, msg.getBytes()); System.out.println("send message txRollback"); // Judge whether the transmission is successful if(!channel.waitForConfirms()){ System.out.println("message send failed"); } else { System.out.println("message send ok"); } channel.close(); connection.close(); } }

Send a batch of waitForConfirms in batch

/** * Batch mode */ public class Send2 { public static final String QUEUE_NAME = "test_queue_confirm2"; public static void main(String[] args) throws IOException, TimeoutException, InterruptedException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false, false, false, null); // The producer calls confirm select to set chancel to confirm mode. Note (an exception will occur if the transaction mechanism is changed to this) channel.confirmSelect(); // Bulk send for (int i = 0; i < 10; i++) { String msg = "hello confirm message"; channel.basicPublish("", QUEUE_NAME, null, msg.getBytes()); } System.out.println("send message txRollback"); // Confirm whether it is sent successfully if(!channel.waitForConfirms()){ System.out.println("message send failed"); } else { System.out.println("message send ok"); } channel.close(); connection.close(); } }

Asynchronous mode

The ConfirmListener() callback method provided by the Channel object contains only deliveryTag (the sequence number of the message issued by the current Channel). We need to maintain an unconfirm message sequence number set for each Channel by ourselves. For each data publish ed, add 1 to the element in the set. Each time the handleAck method is called back, the unconfirm set deletes a corresponding (multiple=false) or multiple (multiple=true) record. From the perspective of program running efficiency, this unconfirm set is better to adopt the ordered set SortedSet storage structure.

producer:

/** * asynchronous */ public class Send3 { public static final String QUEUE_NAME = "test_queue_confirm3"; public static void main(String[] args) throws IOException, TimeoutException { Connection connection = ConnectionUtil.getConnection(); Channel channel = connection.createChannel(); channel.queueDeclare(QUEUE_NAME, false,false,false, null); // The producer calls confirm select to set the channel to confirm mode channel.confirmSelect(); // Store unconfirmed message ID final SortedSet<Long> confirmSet = Collections.synchronizedSortedSet(new TreeSet<Long>()); // Monitor channel channel.addConfirmListener(new ConfirmListener(){ // No problem handleAck @Override public void handleAck(long deliveryTag, boolean multiple) throws IOException { if(multiple){ System.out.println("[handleAck]-----multiple true"); confirmSet.headSet(deliveryTag+1).clear(); } else { System.out.println("[handleAck]-----multiple false"); confirmSet.remove(deliveryTag); } } // handleNack has a problem @Override public void handleNack(long deliveryTag, boolean multiple) throws IOException { if(multiple){ System.out.println("[N]handleNack-----multiple"); confirmSet.headSet(deliveryTag + 1).clear(); } else { System.out.println("[N]handleNack-----multiple false"); confirmSet.remove(deliveryTag); } } }); String msgStr = "ssss"; while(true){ long seqNo = channel.getNextPublishSeqNo(); channel.basicPublish("", QUEUE_NAME, null, msgStr.getBytes()); confirmSet.add(seqNo); } } }

Message response and message persistence

Message response

boolean autoAck = false; //false manual receipt

channel.basicConsume(QUEUE_NAME, autoAck, defaultConsumer);

boolean autoAck =true; (auto ack mode) once rabbitmq distributes the message to the consumer, it will be removed from memory
In this case: if the executing consumer is killed, the processing message will be lost.

boolean autoAck =false; (manual mode). If one consumer hangs up, it will be delivered to other consumers. Rabbitmq supports message response. The consumer sends a message response to tell rabbitmq that I have finished processing this message. You can delete it, and then rabbitmq will delete the message in memory.

Message response is on by default and false by default

Message acknowledgment:

If rabbitmq hangs, the message will still be lost

Message persistence
Queue.DeclareOk queueDeclare(String queue, boolean durable, boolean exclusive, boolean autoDelete, Map<String, Object> arguments) throws IOException;

boolean durable = false;

channel.queueDeclare(QUEUE_NAME, false, false, false,null);

We can't change the boolean durable = false to true in the program. Even if the code is correct, it won't run successfully! Because we have defined a test_work_queue. This queue is persistent. rabbitmq does not allow redefining (different parameters) an existing queue

Exchange (switch forwarder)

On the one hand, it receives messages from producers, and on the other hand, it pushes messages to queues

open relay

void basicPublish(String exchange, String routingKey, BasicProperties props, byte[] body) throws IOException;

String exchange: switch name

channel.basicPublish("", QUERE_NAME, null, message.getBytes());

Type:

fanout (do not process route key)

Direct (process route key)

Routing mode:

21 June 2020, 06:42 | Views: 2486

Add new comment

For adding a comment, please log in
or create account

0 comments