rabbitmq高级特性(消息手动确认)

为了保证消息不丢失,从生产者两种模式(确认模式和返回模式)到消费者手动确认的一个大整合

生产者

1.maven依赖

<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>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <!-- 用于rabbitmq发送json消息 -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.5</version>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>

2.配置文件yml

server:
  port: 8001

spring:
  rabbitmq:
    host: 192.168.56.101
    port: 5672
    virtual-host: /ems
    username: admin
    password: admin
    # 开启确认模式
    publisher-confirms: true
    # 开启回退模式
    publisher-returns: true

3.编写rabbitmq配置类RabbitmqConfig,包含交换机、队列、绑定队列与交换机、设置确认模式和返回模式以及消息转换器

/**
 * @author xiaozikang
 * @date 2020/10/10 11:02
 * @Email:xiaozikangwy@163.com
 */

@Configuration
public class RabbitmqConfig {

    public static final String CONFIRM_EXCAHNGE = "confirmExchange";
    public static final String CONFIRM_QUEUE = "confirmQueue";

    // 交换机
    @Bean("confirmExchange")
    public Exchange confirmExchange(){
        return ExchangeBuilder.directExchange(CONFIRM_EXCAHNGE).durable(true).build();
    }

    // 队列
    @Bean("confirmQueue")
    public Queue confirmQueue(){
        return QueueBuilder.durable(CONFIRM_QUEUE).build();
    }

    // 绑定队列与交换机
    @Bean
    public Binding binding(
            @Qualifier("confirmQueue") Queue confirmQueue,
            @Qualifier("confirmExchange") Exchange confirmExchange
    ){
        return BindingBuilder.bind(confirmQueue).to(confirmExchange).with("confirm").noargs();
    }

    @Bean
    public RabbitTemplate rabbitTemplate(ConnectionFactory connectionFactory){
        RabbitTemplate rabbitTemplate = new RabbitTemplate(connectionFactory);
        // 定义消息转换器Jackson2JsonMessageConverter,发送json数据
        rabbitTemplate.setMessageConverter(producerJackson2MessageConverter());
        // 设置开启Mandatory,如果消息没路由到队列,则返回给消息发送方(如果不开启,默认丢弃消息)
        rabbitTemplate.setMandatory(true);
        // 定义确认模式
        rabbitTemplate.setConfirmCallback(new RabbitTemplate.ConfirmCallback() {
            @Override
            public void confirm(CorrelationData correlationData, boolean ack, String cause) {
                /**
                 *  correlationData 相关配置信息
                 *  ack exchange交换机是否成功收到了消息,true成功
                 *  cause 失败原因
                 */
                if (ack){
                    System.out.println("exchange成功收到消息");
                }else {
                    System.out.print("未收到消息:" + cause);
                    // 可以做些处理,再次发送
                }
            }
        });

        // 定义返回模式
        rabbitTemplate.setReturnCallback(new RabbitTemplate.ReturnCallback() {
            @Override
            public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
                /**
                 *  message 消息对象
                 *  replyCode 错误码
                 *  replyText 错误信息
                 *  exchange 交换机
                 *  routingKey 路由键
                 */
                System.out.println("回调函数执行了");
            }
        });
        return rabbitTemplate;
    }

    @Bean
    public Jackson2JsonMessageConverter producerJackson2MessageConverter(){
        return new Jackson2JsonMessageConverter();
    }

}

4.实体类(主要用于测试发送json消息)

@Data
@NoArgsConstructor
@AllArgsConstructor
public class User implements Serializable {
    private String name;
    private Integer age;
}

5.发送消息

@Test
    public void testf01(){
        User user = new User("小明",10);
        for (int i = 0; i < 5; i++) {
            rabbitTemplate.convertAndSend(RabbitmqConfig.CONFIRM_EXCAHNGE,"confirm",user);
        }

    }

消费者

1.maven依赖

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-amqp</artifactId>
        </dependency>

        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
            <exclusions>
                <exclusion>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework.amqp</groupId>
            <artifactId>spring-rabbit-test</artifactId>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.7.5</version>
        </dependency>

2.配置文件yml

server:
  port: 9020

spring:
  rabbitmq:
    host: 192.168.56.101
    port: 5672
    virtual-host: /ems
    username: admin
    password: admin
    listener:
      simple:
        # 消费手动确认
        acknowledge-mode: manual
        # 消费者每次从队列获取的消息数量。此属性当不设置时为:轮询分发,设置为1为:公平分发
        prefetch: 2
        # 指定最小的消费者数量
        # concurrency: 1
        # 指定最大的消费者数量
        # max-concurrency: 2

3.编写配置类(这边主要用于接受json类型消息)

/**
 * @author xiaozikang
 * @date 2020/10/12 17:50
 * @Email:xiaozikangwy@163.com
 */
@Configuration
public class RabbitConfig implements RabbitListenerConfigurer {

    @Override
    public void configureRabbitListeners(RabbitListenerEndpointRegistrar registrar) {
        registrar.setMessageHandlerMethodFactory(messageHandlerMethodFactory());
    }

    @Bean
    MessageHandlerMethodFactory messageHandlerMethodFactory() {
        DefaultMessageHandlerMethodFactory messageHandlerMethodFactory = new DefaultMessageHandlerMethodFactory();
        messageHandlerMethodFactory.setMessageConverter(consumerJackson2MessageConverter());
        return messageHandlerMethodFactory;
    }

    @Bean
    public MappingJackson2MessageConverter consumerJackson2MessageConverter() {
        return new MappingJackson2MessageConverter();
    }
}

4.消费消息

@Component
public class Consumer {

    @RabbitListener(queues = "confirmQueue")
    public void process(User user, Channel channel, Message message) throws IOException {
        // 1.接受转换消息
        long deliveryTag = message.getMessageProperties().getDeliveryTag();
        try {
            // 2.处理业务逻辑
            System.out.println("处理业务逻辑。。。。。。");
            // 3.手动签收
            // channel.basicAck(deliveryTag,true);
        } catch (Exception e) {
            // e.printStackTrace();
            // 4.出现异常,拒绝签收
            /**
             * requeue 重回队列
             * multiple false只确认当前consumer一个消息收到,true确认所有consumer获得的消息
             */
            channel.basicNack(deliveryTag,true,true);
        }
    }

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值