環境搭建
項目採用springboot整合rabbitmq完成,所以項目的一些配置都是採用springboot操作
pom配置文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-amqp</artifactId>
</dependency>
mq的基本配置
rabbitmq:
host: localhost
port: 5672
username: guest
password: xxxx
publisher-confirms: true
mq的配置類
package com.example.springbootjpa.mq;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CachingConnectionFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
/**
* @Author: weidl
* @Description:
* @Date: Created in 10:18 2019/5/15
*/
@Configuration
public class MqConfiguration {
/**
* voice
*/
public static final String QUEUE_VOICE_MESSAGE="queue_voice_message";
public static final String EXCHANGE_VOICE_MESSAGE="VoiceMessaging.DomainEvent";
@Bean(EXCHANGE_VOICE_MESSAGE)
public Exchange exchangeVoiceMessage() {
return ExchangeBuilder.fanoutExchange(EXCHANGE_VOICE_MESSAGE).durable(true).build();
}
@Bean(QUEUE_VOICE_MESSAGE)
public Queue queueVoiceMessage() {
return new Queue(QUEUE_VOICE_MESSAGE);
}
@Bean
public Binding queueVoice(@Qualifier(QUEUE_VOICE_MESSAGE) Queue queue, @Qualifier(EXCHANGE_VOICE_MESSAGE) Exchange exchange) {
return BindingBuilder.bind(queue).to(exchange).with("").noargs();
}
}
上邊的內容就是聲明交換機,聲明隊列,將隊列綁定到交換機上。
ExchangeBuilder.fanoutExchange(EXCHANGE_VOICE_MESSAGE).durable(true).build();
這段代碼意思就是聲明的交換機可以進行持久化。
隊列採用了new Queue(QUEUE_VOICE_MESSAGE);這裏默認頁就可以進行持久化操作
消息持久化不僅僅需要上邊兩個持久化方式還必須需要消息持久化,在投遞時指定delivery_mode=> 2(1是非持久化)。
同時設置三個持久化方式,那麼消息就可以被持久化了。
發送消息
public class SendMessageController {
@Autowired
private AmqpTemplate amqpTemplate;
@GetMapping("send")
public void sendMessage(){
Student student=new Student();
student.setId(123);
student.setName("張三");
amqpTemplate.convertAndSend(student);
Object o = amqpTemplate.convertSendAndReceive("VoiceMessaging.DomainEvent", "", student);
System.out.println("消息已經發送,返回的結果爲:{}"+o);
}
@GetMapping("test")
public void test(){
System.out.println("========================發送消息");
}
}
上邊的代碼我們採用了convertSendAndReceive方法這裏離的方法是有返回值操作的,我們可以通過消費者拿到數據然後返回給發送方。
接收消息
@Component
@RabbitListener(queues = "queue_voice_message")
public class ReceiveMessage {
public static int count=0;
@RabbitHandler
public String processC(Student student, Message message){
String msgStr = new String();
System.out.println("------------------>監聽的內容爲:"+msgStr);
System.out.println("這是第"+(count++)+"次重試");
return "消息消費成功";
}
點擊發送消息我們就可以看到創建了隊列和交換機
消費端
------------------>監聽的內容爲:
這是第0次重試
消息已經發送,返回的結果爲:{}消息消費成功
上邊感覺還不錯吧,但是如果我在消費過程正增加如下代碼:
int i=1/0;
那麼在此點擊發送會發現消費端一直在請求。無限次重試,這裏很不友好吧,所以我們需要進行對重試機制加以控制。
listener:
simple:
retry:
# 開啓重試機制
enabled: true
#最大重試次數(默認無數次)
max-attempts: 5
#重試間隔時間
initial-interval: 3000
上邊內容我就不多講了,
拓展一些,如果五次失敗之後,我們可以通過發郵件方式通知管理員。對於每次消費都不一定進行重試,如果是客戶端發送問題我們可以採用重試方式,但是對於消費端出現的問題,我們就沒有必要進行重試操作,因爲一次出現問題,那麼必定每次都會出現。注意,有時候在隊列中一直有消息未被消費,我們更改代碼後也無法消費掉,此時我們可採取進入到rabbitmq的控制檯中找到對應的隊列將其刪除即可。
下一章進行詳解回調相關內容