cola de mensajes no entregados springboot rabbitMQ

¿Qué es la cola de mensajes no entregados?

La cola de mensajes no entregados es en realidad, cuando nuestro procesamiento de la cola de negocios falla (como lanzar una excepción y alcanzar el límite superior de reintento), el mensaje se volverá a enviar a otro Exchange (Intercambios de mensajes no entregados) y el Exchange será redirigido a él de acuerdo con la clave de enrutamiento. Otra cola, vuelva a procesar el mensaje en esta cola.

Este artículo integra rabbitMQ a través de springboot, configura una cola normal y una cola de mensajes no entregados. La cola normal establece el tiempo máximo de supervivencia de un mensaje. Cuando el mensaje en la cola supera el tiempo de supervivencia y no se ha consumido, el mensaje se almacenará en la cola de mensajes no entregados .

Productor

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.sunyuqi</groupId>
    <artifactId>com.sunyuqi</artifactId>
    <version>1.0-SNAPSHOT</version>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.1.RELEASE</version>
    </parent>

    <properties>
        <java.version>1.8</java.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.1.37</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

Archivo de configuración

spring.rabbitmq.host=192.168.130.128
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin


##开启消息确认机制
#spring.rabbitmq.publisher-confirms=true
#spring.rabbitmq.listener.direct.acknowledge-mode=manual

#设置交换器名称
mq.config.exchange=direct_exchange
#设置队列的路由键
mq.config.queue.routing.key=test_key

Clase de entidad

package com.sunyuqi.entity;

import java.io.Serializable;

public class Student implements Serializable {
    
    
    private Long id;
    private String name;
    private Integer age;
    private String sex;

    public Long getId() {
    
    
        return id;
    }

    public void setId(Long id) {
    
    
        this.id = id;
    }

    public String getName() {
    
    
        return name;
    }

    public void setName(String name) {
    
    
        this.name = name;
    }

    public Integer getAge() {
    
    
        return age;
    }

    public void setAge(Integer age) {
    
    
        this.age = age;
    }

    public String getSex() {
    
    
        return sex;
    }

    public void setSex(String sex) {
    
    
        this.sex = sex;
    }

    @Override
    public String toString() {
    
    
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", age=" + age +
                ", sex='" + sex + '\'' +
                '}';
    }
}

Clase de productor

package com.sunyuqi.routing;

import com.sunyuqi.entity.Student;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

@Component
public class ProducerApp {
    
    
    @Autowired
    private RabbitTemplate rabbitTemplate;

    //exChange 交换器
    @Value("${mq.config.exchange}")
    private String exChange;

    //routingkey 路由键
    @Value("${mq.config.queue.routing.key}")
    private String routingKey;
    /**
     * 发送消息的方法
     * @param msg
     */
    public void send(String msg){
    
    
 		this.rabbitTemplate.convertAndSend(exChange,routingKey,msg);
    }

    public void send(Student student){
    
    
    	this.rabbitTemplate.convertAndSend(exChange,routingKey,student);
    }

    public void send(Message msg){
    
    
        this.rabbitTemplate.convertAndSend(exChange,routingKey,msg);
    }
}

Clase de arranque

package com.sunyuqi;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootdemoApplication {
    
    

	public static void main(String[] args) {
    
    
		SpringApplication.run(SpringbootdemoApplication.class, args);
	}

}

Clase de prueba, enviar mensaje

package sunyuqi;

import com.alibaba.fastjson.JSON;
import com.sunyuqi.SpringbootdemoApplication;
import com.sunyuqi.entity.Student;
import com.sunyuqi.routing.ProducerApp;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.core.MessageBuilder;
import org.springframework.amqp.core.MessageProperties;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest(classes = SpringbootdemoApplication.class)
public class QueueTest {
    
    

    @Autowired
    private ProducerApp producerApp;

    @Test
    public void test() throws InterruptedException {
    
    

        Student student = new Student();
        student.setId(1L);
        student.setAge(18);
        student.setName("jac");
        student.setSex("男");
        String s = JSON.toJSONString(student);
        Message message = MessageBuilder.withBody(s.getBytes())
                .setContentType(MessageProperties.CONTENT_TYPE_JSON).setContentEncoding("utf-8").build();
        producerApp.send(message);
    }
}

consumidor

El archivo pom y la clase de entidad son los mismos que los del
archivo de configuración del productor

spring.rabbitmq.host=192.168.130.128
spring.rabbitmq.username=admin
spring.rabbitmq.password=admin


#开启消息确认机制
spring.rabbitmq.publisher-confirms=true
#消息监听器类型
spring.rabbitmq.listener.type=direct
#开启手动确认消息
spring.rabbitmq.listener.direct.acknowledge-mode=manual

#设置交换器名称
mq.config.exchange=direct_exchange
#设置队列的路由键
mq.config.queue.routing.key=test_key
#设置队列名称
mq.config.queue=test_queue



#设置死信交换器名称
mq.config.dead_exchange=direct_dead_exchange
#设置死信队列的路由键
mq.config.dead_queue.routing.key=test_dead_key
#设置死信队列名称
mq.config.dead_queue=dead_queue

Cola de mensajes no entregados

package sunyuqi.routing;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.messaging.handler.annotation.Payload;
import org.springframework.stereotype.Component;
import sunyuqi.entity.Student;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

@Component
@RabbitListener(bindings = {
    
    
        @QueueBinding(value = @Queue(value = "${mq.config.dead_queue}",autoDelete = "false"),
        exchange = @Exchange(value = "${mq.config.dead_exchange}", type = ExchangeTypes.DIRECT,autoDelete = "false"),
        key = "${mq.config.dead_queue.routing.key}"),

})
public class DeadConsumerApp {
    
    

    @RabbitListener(queues = "${mq.config.dead_queue}")
    @RabbitHandler
    public void process(@Payload Message msg,Channel channel) throws IOException, TimeoutException {
    
    
        String s = new String(msg.getBody());
        Student student = JSON.parseObject(s, Student.class);
        System.out.println("进入死信队列的消息:"+student);
        channel.basicAck(msg.getMessageProperties().getDeliveryTag(),false);
    }
}

Cola normal (esta cola está configurada con un conmutador normal y enlazada con el conmutador de mensajes no entregados y la cola de mensajes no entregados)

package sunyuqi.routing;

import com.alibaba.fastjson.JSON;
import com.rabbitmq.client.Channel;
import org.springframework.amqp.core.ExchangeTypes;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.stereotype.Component;
import sunyuqi.entity.Student;
import java.io.IOException;
import java.util.concurrent.TimeoutException;

@Component
@RabbitListener(bindings = {
    
    
        @QueueBinding(
        value = @Queue(value = "${mq.config.queue}", autoDelete = "false", arguments = {
    
    
                //绑定死信交换机
                @Argument(name = "x-dead-letter-exchange", value = "${mq.config.dead_exchange}"),
                //绑定死信队列
                @Argument(name = "x-dead-letter-routing-key", value = "${mq.config.dead_queue.routing.key}"),
                //配置最大存活时间
                @Argument(name = "x-message-ttl", value = "10000", type = "java.lang.Integer")
        }),
        //配置普通交换机
        exchange = @Exchange(value = "${mq.config.exchange}", type = ExchangeTypes.DIRECT, autoDelete = "false"),
        key = "${mq.config.queue.routing.key}"),
})
public class ConsumerApp {
    
    

    @RabbitListener(queues = "${mq.config.queue}")
    @RabbitHandler
    public void process(Message message, Channel channel) throws IOException, TimeoutException {
    
    
        try {
    
    
            int a = 1/0;
            //手动确认消息正确消费
            String  msg = new String(message.getBody());
            Student student = JSON.parseObject(msg,Student.class);
            System.out.println("正常处理消息: "+student);channel.basicAck(message.getMessageProperties().getDeliveryTag(), false);

        } catch (Exception e) {
    
    
        //手动nack,将消息放入死信队列
            channel.basicNack(message.getMessageProperties().getDeliveryTag(), false, false);
        }
    }
}

En el código del consumidor, escribimos manualmente una excepción, int a =
1/0 ; después de capturar la excepción, manualmente nack, el mensaje se colocará en la cola de mensajes no entregados para su procesamiento.

Primero ejecutamos la clase de arranque del consumidor para crear automáticamente los conmutadores y colas correspondientes.
Luego ejecute la clase de prueba del productor y envíe un mensaje, la
consola imprime el resultado:
Inserte la descripción de la imagen aquí
el mensaje ingresó a la cola de mensajes no entregados.
En este punto detenemos al consumidor y le enviamos un mensaje nuevamente.
Inserte la descripción de la imagen aquí
Se encontró un mensaje en la cola y, después de diez segundos (lo configuramos en diez segundos), el mensaje se transfirió a la cola de mensajes no entregados.
Inserte la descripción de la imagen aquí

Supongo que te gusta

Origin blog.csdn.net/weixin_42494845/article/details/108813060
Recomendado
Clasificación