Cola de mensajes fallidos de RabbitMQ 11

cola de mensajes fallidos

Descripción general

Si no hay ningún consumidor para procesar los datos en la cola de mensajes, siempre ocupará el espacio de la cola de mensajes.

Por ejemplo, en el escenario de robo de boletos, después de que un usuario realiza un pedido de un boleto de tren de alta velocidad, tomará un asiento y luego realizará el pago, pero si el usuario no paga a tiempo después de realizar el pedido , el boleto no puede ser ocupado por este usuario todo el tiempo, porque será ocupado por otros. Ya no puede comprar este boleto, por lo que caducará después de un período de tiempo, permitiendo que otros continúen comprando este boleto. .

En este momento, puede utilizar la cola de mensajes fallidos para procesar aún más aquellos pedidos que el usuario no ha pagado a lo largo del tiempo o que el usuario canceló activamente.

Entonces, ¿cómo construir ese modelo de uso? De hecho, es esencialmente un cambio de mensajes no entregados + una cola de mensajes no entregados .

Cuando se determina que un mensaje en la cola normal es un mensaje no entregado, se enviará al conmutador de mensajes no entregados correspondiente y luego a través del conmutador se enviará a la cola de mensajes no entregados. La cola de mensajes no entregados también tiene un consumidor correspondiente para procesar el mensaje.

Generalmente existen tres situaciones en las que se determina que una letra muerta está muerta:

  • El mensaje fue rechazado ( basic.reject/ basic.nack) y requeue = false.
  • El mensaje expiró y no se consumió.
  • La cola de mensajes ha alcanzado su longitud máxima.

generar letras muertas

Mensaje rechazado

  1. Cree un nuevo conmutador de mensajes fallidos y una cola de mensajes fallidos en la clase de configuración y vincúlelos.

    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.Exchange;
    import org.springframework.amqp.core.ExchangeBuilder;
    import org.springframework.amqp.core.Queue;
    import org.springframework.amqp.core.QueueBuilder;
    import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * RabbitMQ配置类
     */
    @Configuration
    public class RabbitMqConfig {
    
        ...
    
        /**
         * 定义消息队列
         * @return 消息队列对象
         */
        @Bean("testQueue")
        public Queue queue(){
            return QueueBuilder
                    // 非持久化类型
                    .nonDurable("test_springboot")
                    // 指定死信交换机
                    .deadLetterExchange("dl.direct")
                    // 指定死信RoutingKey
                    .deadLetterRoutingKey("dl_test_springboot_key")   
                    .build();
        }
    
        /**
         * 构建死信交换机
         * @return 死信交换机
         */
        @Bean
        public Exchange dlExchange(){
            // 创建一个新的死信交换机
            return ExchangeBuilder.directExchange("dl.direct").build();
        }
    
        /**
         * 构建死信队列
         * @return 死信队列
         */
        @Bean
        public Queue dlQueue(){
            return QueueBuilder
                    .nonDurable("dl_test_springboot")
                    .build();
        }
    
        /**
         * 死信交换机和死信队列绑定
         * @param exchange 死信交换机
         * @param queue 死信队列
         * @return 绑定对象
         */
        @Bean
        public Binding dlBinding(@Qualifier("dlExchange") Exchange exchange,
                                 @Qualifier("dlQueue") Queue queue){
            return BindingBuilder
                    .bind(queue)
                    .to(exchange)
                    .with("dl_test_springboot_key")
                    .noargs();
        }
        
        ...
        
    }
  2. Escuche los mensajes de la cola normal y de la cola de mensajes fallidos.

    import cn.codesail.rabbitmq.entity.User;
    import com.rabbitmq.client.Channel;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.amqp.support.AmqpHeaders;
    import org.springframework.messaging.handler.annotation.Header;
    import org.springframework.stereotype.Component;
    
    /**
     * 直连队列监听器
     */
    @Component
    public class DirectListener {
    
        /**
         * 监听正常队列消息
         */
        @RabbitListener(queues = "test_springboot", messageConverter = "jackson2JsonMessageConverter")
        public void receiver(Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, User user) throws Exception {
            // 拒绝消息。第二个参数为true则消息返回队列,第二个参数为false则消息不返回队列,成为死信
            channel.basicReject(deliveryTag, false);
            System.out.println("正常队列接收到消息:" + user);
        }
        
        /**
         * 监听死信队列消息
         */
        @RabbitListener(queues = "dl_test_springboot", messageConverter = "jackson2JsonMessageConverter")
        public void receiverDl(User user) {
            System.out.println("死信队列接收到消息:" + user);
        }
    }

    Si el oyente de mensajes de la cola normal rechaza el mensaje y no lo devuelve a la cola, se convierte en letra muerta y será recibido por el oyente de la cola de mensajes no entregados.

  3. Eliminar la cola original. La cola vinculada a la cola de mensajes no entregados solo se puede crear después de eliminar la cola original.

  4. Productores de implementos.

    import cn.codesail.rabbitmq.entity.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    
    @SpringBootTest
    class RabbitMqSpringBootTests {
    
        /**
         * RabbitTemplate封装了大量的RabbitMQ操作,已经由Starter提供,因此直接注入使用即可
         */
        @Autowired
        private RabbitTemplate rabbitTemplate;
    
        /**
         * 生产者
         */
        @Test
        void producer() {
            
            // 发送Json消息
            User user = new User();
            user.setName("张三");
            user.setAge(18);
            rabbitTemplate.convertAndSend("amq.direct", "test_springboot_key", user);
        }
    
    }
  5. Inicie el productor para enviar mensajes:

    Como puede ver, la cola de mensajes no entregados recibió el mensaje.

Se agotó el tiempo de espera del mensaje y no se consumió.

  1. Establezca el valor TTL de la cola.

    import org.springframework.amqp.core.Queue;
    import org.springframework.amqp.core.QueueBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * RabbitMQ配置类
     * 
     * @author CodeSail
     */
    @Configuration
    public class RabbitMqConfig {
    
        ...
    
        /**
         * 定义消息队列
         * @return 消息队列对象
         */
        @Bean("testQueue")
        public Queue queue(){
            return QueueBuilder
                    // 非持久化类型
                    .nonDurable("test_springboot")
                    // 指定死信交换机
                    .deadLetterExchange("dl.direct")
                    // 指定死信RoutingKey
                    .deadLetterRoutingKey("dl_test_springboot_key")
                    // 如果5秒没处理,就自动删除
                    .ttl(5000)
                    .build();
        }
    
        ...
    }
  2. Cancele la escucha en cola normal.

    import cn.codesail.rabbitmq.entity.User;
    import com.rabbitmq.client.Channel;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.amqp.support.AmqpHeaders;
    import org.springframework.messaging.handler.annotation.Header;
    import org.springframework.stereotype.Component;
    
    /**
     * 直连队列监听器
     */
    @Component
    public class DirectListener {
    
        /**
         * 监听正常队列消息
         */
    //    @RabbitListener(queues = "test_springboot", messageConverter = "jackson2JsonMessageConverter")
    //    public void receiver(Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long deliveryTag, User user) throws Exception {
    //        // 拒绝消息。第二个参数为true则消息返回队列,第二个参数为false则消息不返回队列,成为死信
    //        channel.basicReject(deliveryTag, false);
    //        System.out.println("正常队列接收到消息:" + user);
    //    }
        
        /**
         * 监听死信队列消息
         */
        @RabbitListener(queues = "dl_test_springboot", messageConverter = "jackson2JsonMessageConverter")
        public void receiverDl(User user) {
            System.out.println("死信队列接收到消息:" + user);
        }
    }
  3. Productores de implementos.

    import cn.codesail.rabbitmq.entity.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import java.util.concurrent.TimeUnit;
    
    @SpringBootTest
    class RabbitMqSpringBootTests {
    
        /**
         * RabbitTemplate封装了大量的RabbitMQ操作,已经由Starter提供,因此直接注入使用即可
         */
        @Autowired
        private RabbitTemplate rabbitTemplate;
    
        /**
         * 生产者
         */
        @Test
        void producer() throws InterruptedException {
            
            // 发送Json消息
            User user = new User();
            user.setName("张三");
            user.setAge(18);
            rabbitTemplate.convertAndSend("amq.direct", "test_springboot_key", user);
        }
    
    }
  4. Eliminar la cola original. Solo después de eliminar la cola original se puede crear una cola con un TTL vinculado a la cola de mensajes no entregados.

  5. Inicie el servicio y escuche los mensajes.

  6. Inicie el productor para enviar mensajes y espere 5 segundos:

    Como puede ver, la cola de mensajes no entregados recibió el mensaje.

La cola de mensajes alcanza la longitud máxima

  1. Establezca la longitud máxima de mensajes de la cola.

    import org.springframework.amqp.core.Binding;
    import org.springframework.amqp.core.BindingBuilder;
    import org.springframework.amqp.core.Exchange;
    import org.springframework.amqp.core.ExchangeBuilder;
    import org.springframework.amqp.core.Queue;
    import org.springframework.amqp.core.QueueBuilder;
    import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
    import org.springframework.beans.factory.annotation.Qualifier;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    
    /**
     * RabbitMQ配置类
     */
    @Configuration
    public class RabbitMqConfig {
    
        ...
    
        /**
         * 定义消息队列
         * @return 消息队列对象
         */
        @Bean("testQueue")
        public Queue queue(){
            return QueueBuilder
                    // 非持久化类型
                    .nonDurable("test_springboot")
                    // 指定死信交换机
                    .deadLetterExchange("dl.direct")
                    // 指定死信RoutingKey
                    .deadLetterRoutingKey("dl_test_springboot_key")
                    // 最大长度设定为3
                    .maxLength(3)
                    .build();
        }
    
        ...
        
    }
  2. Cancele la escucha en cola normal.

    import cn.codesail.rabbitmq.entity.User;
    import org.springframework.amqp.rabbit.annotation.RabbitListener;
    import org.springframework.stereotype.Component;
    
    /**
     * 直连队列监听器
     */
    @Component
    public class DirectListener {
    
        /**
         * 监听正常队列消息
         */
    //    @RabbitListener(queues = "test_springboot", messageConverter = "jackson2JsonMessageConverter")
    //    public void receiver(User user) {
    //        System.out.println("正常队列接收到消息:" + user);
    //    }
        
        /**
         * 监听死信队列消息
         */
        @RabbitListener(queues = "dl_test_springboot", messageConverter = "jackson2JsonMessageConverter")
        public void receiverDl(User user) {
            System.out.println("死信队列接收到消息:" + user);
        }
    }
  3. Eliminar la cola original. Solo después de eliminar la cola original se puede crear una cola con una longitud máxima establecida que esté vinculada a la cola de mensajes no entregados.

  4. Definir productor.

    import cn.codesail.rabbitmq.entity.User;
    import org.junit.jupiter.api.Test;
    import org.springframework.amqp.rabbit.core.RabbitTemplate;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.boot.test.context.SpringBootTest;
    import java.util.concurrent.TimeUnit;
    
    @SpringBootTest
    class RabbitMqSpringBootTests {
    
        /**
         * RabbitTemplate封装了大量的RabbitMQ操作,已经由Starter提供,因此直接注入使用即可
         */
        @Autowired
        private RabbitTemplate rabbitTemplate;
    
        /**
         * 生产者
         */
        @Test
        void producer() throws InterruptedException {
            
            for (int i = 0; i < 4; i++) {
                User user = new User();
                user.setName("张三" + i);
                user.setAge(18);
                rabbitTemplate.convertAndSend("amq.direct", "test_springboot_key", user);
            }
        }
    
    }
  5. Inicie el productor para enviar mensajes.

    Como puede ver, el primer elemento de la cola se elimina y se convierte en letra muerta.

    La cola es similar a una tubería: cuando la tubería está llena, la última persona en entrar expulsará a la primera.


Supongo que te gusta

Origin blog.csdn.net/qq_37770674/article/details/130097887
Recomendado
Clasificación