This article has participated in the activity of “New person creation Ceremony”, and started the road of digging gold creation together

1, the preface

 

The last article summarized the more basic uses of RabbitMQ, such as the simplest message sending and load balancing of multiple queues. Several other queue modes are available in Rabbit MQ. This is largely dependent on different types of switches. If you don’t reference a switch in RabbitMQ, producers and consumers of messages are queued directly, which is relatively coupling and limited in functionality. There are four main types of Exchange. Fanout, topic, headers, fanout.

2. Direct transmission type

This is the simplest way mq is used with a switch, which separates the producer from the consumer, who only knows which switch it needs to deliver messages to; The producer only knows which switch to get the message from.

The components of these message queues can be managed through beans in Spring Boot.

@Configuration public class DirectQueueConfig { @Bean public DirectExchange directExchange(){ return new DirectExchange("express.item"); } @Bean public Queue directQueueOne(){ return new Queue("clothes",false,false,true); } @Bean public Queue directQueueTwo(){ return new Queue("cup",false,false,true); } @Bean public Binding directBingOne(DirectExchange directExchange,Queue directQueueOne){ return BindingBuilder.bind(directQueueOne) .to(directExchange) .with("normal"); } @Bean public Binding directBingTwo(DirectExchange directExchange,Queue directQueueTwo){ return BindingBuilder.bind(directQueueTwo) .to(directExchange) .with("fragile"); } @Bean public DirectListener directListener(){ return new DirectListener(); }}Copy the code

For example, the code snippet above creates the exchange, queue, binding, and consumer, respectively.

Several parameters are optional when declaring queues.

 public Queue(String name, boolean durable, boolean exclusive, boolean autoDelete) {
        this(name, durable, exclusive, autoDelete, (Map)null);
    }
Copy the code

Name: indicates the queue name

Durable: Whether it can be durable and whether queues can be restored after the broker restarts.

Exclusive: exclusive. This may be used less often but is a more characteristic parameter. According to the documentation, when declaring an exclusive queue, the queue can only be used by a connection, and the exclusive queue is automatically deleted when the connection is closed, regardless of whether you set autoDELETE.

Auto-delete: automatic deletion. This is easier to understand. When no consumers subscribe to the queue, the queue will be automatically deleted

@Slf4j public class DirectListener { @RabbitListener(queues = "#{directQueueOne.name}") public void normalListener(String message){ log.info("normal express:[{}]",message); } @RabbitListener(queues = "#{directQueueTwo.name}") public void fragileListener(String message){ log.info("fragile express:[{}]",message); }}Copy the code

The simplest way to use this is to declare the name of the queue to listen to. You can use SPEL expressions to parameterize variables and decouple them, or you can write strings to declare them.

 public void directSendMessage(String message, String routingKey) {
        LocalDateTime now = LocalDateTime.now();
        log.info("producer direct time:[{}]", now.toString());
        rabbitTemplate.convertAndSend(directExchange.getName(), routingKey, message);
        log.info("producer direct message:[{}]", message);
    }
Copy the code

Send messages can use the above code snippet using spring configuration in good rabbitTemplate convertAndSend method of three parameters represent which is sent to the switch, which use the routing key (is before binding queue and switch used in the key, so messages will know to which the queue). The last one is the delivery message. That’s the end of a complete direct message

3. Broadcast type

This is also a common switch pattern, which is to post messages to all subscribed queues and let all listening queue consumers consume the queue.

@Configuration public class FanoutQueueConfig { @Bean public FanoutExchange fanoutExchange(){ return new FanoutExchange("express.fanout"); } @Bean public Queue fanoutQueueOne(){ return new Queue("fanout1",false,false,true); } @Bean public Queue fanoutQueueTwo(){ return new Queue("fanout2",false,false,true); } @Bean public Binding bindingOne(FanoutExchange fanoutExchange,Queue fanoutQueueOne){ return BindingBuilder.bind(fanoutQueueOne) .to(fanoutExchange); } @Bean public Binding bindingTwo(FanoutExchange fanoutExchange,Queue fanoutQueueTwo){ return BindingBuilder.bind(fanoutQueueTwo) .to(fanoutExchange); } @Bean public FanoutListener fanoutListener(){ return new FanoutListener(); }}Copy the code

The code here is basically the same as the direct type, except that it uses a Fanout switch

The code snippet for the consumer is shown below

@Slf4j public class FanoutListener { @RabbitListener(queues = "#{fanoutQueueOne.name}") public void fanoutListenerOne(String msg){ log.info("fanoutQueue1 receive:[{}],time:[{}]",msg, LocalDateTime.now()); } @RabbitListener(queues = "#{fanoutQueueTwo.name}") public void fanoutListenerTwo(String msg){ log.info("fanoutQueue2 receive:[{}],time:[{}]",msg,LocalDateTime.now()); }}Copy the code

4. Subject type

This is probably the most widely used type of switch. The difference is that there is a special routing key, which means THAT I can choose which queue to receive my delivery. The routing key is a marker parameter between the connection queue and the switch. Routing keys in topic switches have rules that require words to be concatenated by dots. Two special characters have been added to match:

: the asterisk indicates that it can be replaced by a single word. For example, the routing key is orange.. Orange.blue. Max matches but orange.max does not;

# : The hash sign can be replaced by any word (0 or more). For example, if the routing key is orange.*. Max then orange.blue.

@Configuration public class TopicQueueConfig { @Bean public TopicExchange topicExchange(){ return new TopicExchange("express.topic"); } @Bean public Queue topicQueueOne(){ return new Queue("food",false,false,true); } @Bean public Queue topicQueueTwo(){ return new Queue("appliance",false,false,true); } @Bean public Queue topicQueueThree(){ return new Queue("fruit",false,false,true); } @Bean public Binding topicBindingOne(TopicExchange topicExchange,Queue topicQueueOne){ return BindingBuilder.bind(topicQueueOne) .to(topicExchange) .with("food.delicatessen"); } @Bean public Binding topicBindingTwo(TopicExchange topicExchange,Queue topicQueueTwo){ return BindingBuilder.bind(topicQueueTwo) .to(topicExchange) .with("appliance.*.bigSize"); } @Bean public Binding topicBindingThree(TopicExchange topicExchange,Queue topicQueueThree){ return BindingBuilder.bind(topicQueueThree) .to(topicExchange) .with("fruit.#"); } @Bean public TopicListener topicListener(){ return new TopicListener(); }}Copy the code

The topic exchange, queue, and consumer are created here. In fact, the routing key with point splicing can be considered to build a tree data structure, which is convenient to achieve the purpose of message delivery.

@RabbitListener(queues = "#{topicQueueOne.name}")
    public void foodListener(String message) {
        log.info("receive delicatessen food:[{}]", message);
    }

    @RabbitListener(queues = "#{topicQueueTwo.name}")
    public void applianceListener(String message) {
        log.info("receive big appliance:[{}]", message);
    }

    @RabbitListener(queues = "#{topicQueueThree.name}")
    public void fruitListener(String message) {
        log.info("receive any fruit:[{}]", message);
    }


    @RabbitListener(bindings = @QueueBinding(
            value = @Queue(value = "web_queue", durable = "false", autoDelete = "true", exclusive = "false"),
            exchange = @Exchange(value = "web", type = ExchangeTypes.TOPIC),
            key = {"web.info"}
    ))
    public void webListener(String message) {
        log.info("web info:[{}]", message);
    }
Copy the code

There are two ways to do this, one is to use the RabbitListerner annotation to declare the name of the listening queue to listen for consumption messages. The other is to use this annotation to create a queue, a switch, and a consumer at the same time, and declare the bound routing key. This completes the configuration of an example topic switch