RabbitMq學習筆記-實戰篇-spring boot整合

1、JSON序列化與反序列化

要實現消息跨平臺,需要配置消息JSON序列化(配置見代碼實現),就可以實現不同語言之間互相發送/接收消息,還可以直接用RabbitMQ控制檯發送消息。

從RabbitMQ控制檯發送消息,指定properties  content_type=application/json

2、消息重試機制

見application.yml配置文件,手動模式下,當消費端消費拋異常時,消息會進行重試。消息等待重試時,會阻塞,直到重試都失敗後,纔會消費下一條消息。

pom.xml

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

application.yml

spring:
  rabbitmq:
    addresses: localhost:5672
    username: guest
    password: guest
    publisher-confirms: true #推送確認
    publisher-returns: true #推送退回
    listener:
      simple:
        acknowledge-mode: MANUAL # 手動確認模式
        prefetch: 10000 #最多允許多少個未應答
        retry:
          enabled: true #是否開啓消費者重試(爲false時關閉消費者重試,這時消費端代碼異常會一直重複收到消息)
          max-attempts: 3 #最大重試次數
          initial-interval: 10S #重試間隔時間,如果重試間隔大於10S,必須設置最大重試間隔,否則只能小於等於10S
          max-interval: 10S #最大重試間隔時間,默認10S

RabbitTemplateConfig.java


@Slf4j
@Configuration
public class RabbitTemplateConfig implements RabbitTemplate.ConfirmCallback , RabbitTemplate.ReturnCallback{

    @Autowired
    private RabbitTemplate rabbitTemplate;
    @Autowired
    private SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory;

    @PostConstruct
    public void init() {
        //指定 ConfirmCallback
        rabbitTemplate.setConfirmCallback(this);
        rabbitTemplate.setReturnCallback(this);
        // 使用 JSON 序列化與反序列化
        rabbitTemplate.setMessageConverter(new Jackson2JsonMessageConverter());
        rabbitListenerContainerFactory.setMessageConverter(new Jackson2JsonMessageConverter());
    }

    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        if(!ack){
            log.info("發送MQ消息失敗,ID:{}, 原因: {}", correlationData.toString(), cause);
        }
    }

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        log.info("發送MQ消息回退: {}, {}, exchange:{}, routing:{}" + JSON.toJSONString(message), replyCode, exchange, routingKey);
    }
}

Hello1Receiver.java

/**
 * 普通模式消費端
 */
@Slf4j
@Component
public class Hello1Receiver {

    @RabbitListener(queuesToDeclare = @Queue("hello")) // 需要注意,改註解要寫在方法上,不然JSON序列化會失效
    public void process(Hello bean, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        // TODO 業務邏輯
        TimeUnit.SECONDS.sleep(2);
        // 手動確認
        channel.basicAck(tag, false);
        log.info("hello1消息消費成功params:{}", JSON.toJSONString(bean));
    }
}

TopicReceiver.java

/**
 * topic模式消費端
 */
@Slf4j
@Component
public class TopicReceiver {

    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = "topic.exchange",type = "topic"),
            value = @Queue(value = "consumer_queue"),
            key = "key.#"
    ))
    public void key(Hello bean, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        // TODO 業務邏輯

        // 手動確認
        channel.basicAck(tag, false);
        log.info("topic-key消息消費成功params:{}", JSON.toJSONString(bean));
    }


    @RabbitListener(bindings = @QueueBinding(
            exchange = @Exchange(value = "topic.exchange",type = "topic"),
            value = @Queue(value = "consumer_queue"),
            key = "value.#"
    ))
    public void value(Hello bean, Channel channel, @Header(AmqpHeaders.DELIVERY_TAG) long tag) throws Exception {
        // TODO 業務邏輯

        // 手動確認
        channel.basicAck(tag, false);
        log.info("topic-value消息消費成功params:{}", JSON.toJSONString(bean));
    }
}

HelloProducerTest.java

public class HelloProducerTest extends BasicTest{

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Test
    public void sendTest() throws Exception {
        for (int i = 0; i < 10; i++) {
            Hello bean = Hello.builder()
                    .id(i)
                    .title("hello")
                    .content("你好")
                    .build();
            amqpTemplate.convertAndSend("hello", bean);
        }
        TimeUnit.SECONDS.sleep(5);
    }
}

TopicProducerTest.java

public class TopicProducerTest extends BasicTest{

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Test
    public void sendTest() {
        Hello bean = Hello.builder()
                .id(1)
                .title("hello")
                .content("你好")
                .build();
        amqpTemplate.convertAndSend("topic.exchange", "key.hello", bean );
        amqpTemplate.convertAndSend("topic.exchange", "value.hello", bean );
    }
}

demo下載

https://download.csdn.net/download/kuyuyingzi/12235976

參考資料:

https://www.rabbitmq.com/getstarted.html

https://www.jianshu.com/p/911d987b5f11

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章