1. RabbitMQ combat skills

1.1. Introduction

Due to the project, we will be dealing with RabbitMQ more, so let’s take a good look at RabbitMQ application skills and try to avoid future pit mining

Summary of 1.2.

RabbitMQ has several important concepts: virtual hosts, switches, queues and bindings

  • Virtual host: A virtual host holds a set of switches, queues, and bindings that we can control from the granularity of the virtual host level
  • Switch: Exchange forwards messages. It does not store messages. If there is no Queue bound to Exchange, it simply discards the data sent by the producer. Another important concept associated with the switch is the routing key, which determines which queue messages are forwarded to
  • Binding: Binds switches to queues. It is a many-to-many relationship, that is, multiple switches can be bound to the same queue, or one switch can be bound to multiple queues

1.3. The switch

Switches have four types of modes: Direct, Topic, Headers, and Fanout

1.3.1. Direct Exchage

The Direct mode uses the default switch of RabbitMQ. It is the simplest mode and is suitable for simple scenarios

As shown in the following figure, in Direct mode, we need to create different queues. By default, the switch uses the Routing key value to determine which queue to forward to

1.3.2. The Topic Exchange

Topic patterns are matched primarily by wildcard characters, which are similar to fuzzy matching, and when matched with routing keys the switch can forward messages to a specific queue

  • The routing key is a string consisting of a period (.) (.), for examplea.b.c
  • (*) represents a word for a designated position, (#) stands for zero or more words, such asa.*.b.#B can be followed by n words, e.ga.x.b.c.d.e

The difference between Topic mode and Direct mode is that the switch needs to be specified by itself. Routing keys support fuzzy matching, for example:

rabbitTemplate.convertAndSend("topicExchange","a.x.b.d", " hello world!" );Copy the code

1.3.3. Headers Exchage

Headers also matches by rule, but not by routing key. Headers has a custom matching rule that sets the matching key value in the Headers attribute of a message. When one or all of these key pairs match, the message is sent to the corresponding queue

1.3.4. The Fanout Exchange

Fanout is the well-known broadcast mode, which does not require a routing key and sends messages to all queues bound to it, even if routing keys are configured, it is ignored

1.4. Complications

  1. First of all, in the Direct mode, the case of one producer and one consumer corresponds to one sender and one queue A to receive. There is no doubt that what is sent receives what
  2. In Direct mode, when a producer sends a message, multiple consumers are opened, i.e., multiple queues are opened. In this case, the message is evenly distributed by multiple consumers without repeated consumption (if ack is normal).
  3. In Topic mode, a switch is bound to two queues and the routing keys overlap, as shown in the following codetopic.messageSend messages, queuequeueMessageandqueueMessagesAll receive the same message, which means,The Topic pattern can be implemented in a form similar to the broadcast patternAnd even more flexible, whether it can forward messages is determined by routing keys.
  4. Compared with Fanout mode, if we want to group the consumer queue, we need to specify a different routing key; In Fanout mode, different switch and queue bindings need to be specified
@Configuration public class TopicRabbitConfig { final static String message = "topic.message"; final static String messages = "topic.messages"; @Bean public Queue queueMessage() { return new Queue(TopicRabbitConfig.message); } @Bean public Queue queueMessages() { return new Queue(TopicRabbitConfig.messages); } @Bean TopicExchange exchange() { return new TopicExchange("exchange"); } @Bean Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) { return BindingBuilder.bind(queueMessage).to(exchange).with("topic.message"); } @Bean Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) { return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#"); }}Copy the code

1.5. Springboot configuration

Our common configuration is as follows

spring.rabbitmq.addresses=localhost:5672 spring.rabbitmq.username=user spring.rabbitmq.password=123456 Spring. The rabbitmq. Virtual - host = / spring. The rabbitmq. Connection timeout = 1000 # # set up to monitor restrictions: Maximum 10, The default 5 spring. The rabbitmq. Listener. Simple. Concurrency = 5 spring. The rabbitmq. Listener. Simple. Max - concurrency = 10 spring.rabbitmq.publisher-confirms=true spring.rabbitmq.publisher-returns=true spring.rabbitmq.template.mandatory=true spring.rabbitmq.listener.simple.acknowledge-mode=manualCopy the code

The last four configurations need to be explained:

  • spring.rabbitmq.publisher-confirmsIf this parameter is set to true, the MQ broker receives the message after the producer message is sent. Sending an acknowledgement acknowledgement confirms the receipt. If this parameter is not set to true, the message may be lost
  • spring.rabbitmq.publisher-returnsTrue: if the message cannot reach the MQ Broker, the listener will be used to process the unreachable message. This can occur if the routing key is not configured properly or IF MQ is down
  • spring.rabbitmq.template.mandatoryWhen the above two are true, this must be true, otherwise the above two will not work
  • spring.rabbitmq.listener.simple.acknowledge-modeThis ismanualThe actual production should be set to manual to ensure that your business is completed. Pay attention to the idempotency of business and can be called repeatedly. The manual confirmation code is shown in the following example
@Component public class RabbitReceiver { @RabbitListener(bindings = @QueueBinding( value = @Queue(value = "queue-1", durable="true"), exchange = @Exchange(value = "exchange-1", durable="true", type= "topic", ignoreDeclarationExceptions = "true"), key = "springboot.*" ) ) @RabbitHandler public void onMessage(Message message, Channel channel) throws Exception { System.err.println("--------------------------------------"); System.err.println(" Payload: "+ message.getpayload ()); Long deliveryTag = (Long)message.getHeaders().get(AmqpHeaders.DELIVERY_TAG); BasicAck (deliveryTag, false); }}Copy the code

1.6. Queue properties

  1. Queue: indicates the name of a queue
  2. Durable: The value of true indicates that data in queues is persisted to disks, preventing data loss during mq downtime and restart
  3. Exclusive: Only one current connection is allowed to access the queue. New connections are not allowed to enter the queue. Otherwise, an error is reported
  4. AutoDelete: If the value is true, the Connection is automatically deleted. If no Connection is connected to the queue, the Connection is automatically deleted
  5. argumentsThis parameter is used to add some extra parameters, as shown in the following image
    • Such as addingx-message-ttlIf the value is 5000, the message will expire if it is not processed for more than 5 seconds.
    • x-expiresSetting 120000 means that the queue will be deleted if it is not consumed within 2 minutes;
    • x-max-length.x-max-length-bytesRepresents the maximum length and number of bytes of data to transmit
    • x-dead-letter-exchange.x-dead-letter-routing-keyRepresents dead letter switches and dead letter routes in queue attributes that need to expire or fail processing. These data will be forwarded to dead letter queues for storage. Create a normal switch and queue bindingx-dead-letter-exchangeThe routing key must match the routing key of the dead letter queue
    • x-max-priority“Indicates the priority. The value ranges from 0 to 255This priority makes sense when messages pile up, the higher the number, the higher the priority
    • x-queue-modeAs for thelazyThe lazy queue mode stores messages generated by producers directly to disk compared to the default mode. This of course increases THE I/O overhead, but it is suitable for situations where large amounts of messages are piled up. When a large number of messages accumulate and the memory is insufficient, messages are dumped to disks. This process is time-consuming and new messages cannot be received during the process. If you want to convert a normal queue to a lazy queue, you need to delete the original queue and create another lazy queue binding.
! [](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/10/29/16e15a7f22c92c58~tplv-t2oaga2asx-image.imag e)Copy the code

1.7. Switch Properties

  1. Exchange: indicates the switch name
  2. Type: indicates the switch type
  3. Durable: Persistent, same queue
  4. AutoDelete: indicates whether to automatically delete the queue
  5. Internal: If the value is true, the exchange cannot be used by the client to push messages. The exchange is only used for binding between exchanges.
  6. Arguments: Additional arguments, currently only onealternate-exchange, indicates that when the producer sends messages to the switch but cannot route to the queue of the switch, the producer attempts to route to the switch specified by this parameter. If the routing key matches, the producer routes to the switchalternate-exchangeThe specified queue, equivalent to forwarding, matches the last parameterinternalIf you do not want the local switch to function as a routing queue, you can set this parameterinternalIf true, all messages are forwarded toalternate-exchangeA specified switch by which to route a specified queue,
    • The diagram below:exchange0Set upalternate-exchangeSwitches forexchange1, the producer sends data toexchange0The key route fortest1In theexchange0If the route cannot be routed, it is forwarded toexchange1Check whether the route matches and send the route to the queuequeue1
! [](https://p1-jj.byteimg.com/tos-cn-i-t2oaga2asx/gold-user-assets/2019/10/29/16e15a7f4c0a2b45~tplv-t2oaga2asx-image.imag e)Copy the code

1.8. Disks and Memory

In the RabbitMQ admin interface, when clustered, you can see that the Info field in the Nodes may be disc or RAM, indicating disk storage or memory storage. In fact, for clustered deployment we need at least one disk store, which means that metadata such as switches, queues, bindings and users can be persisted to disk. RabbitMQ can be restored to its original state after a single restart. Memory storage also has its advantages, that is, it is more efficient and faster

1.9. Error reporting cases

  • When the following error is reported, you must have an exclusive queue, that is, setexclusiveAttribute, because different channels created for the same connection can access the same queue, the resource is locked because of this exclusive attribute, which is the following error.
  • So that tells us that if you set the queue toexclusiveProperty, then do not create a new connection to access the same queue
ESOURCE_LOCKED - cannot obtain exclusive access to locked queue xxxxxxCopy the code

Welcome to pay attention to the public number, learning and progress together