RabbitMq學習筆記(3)_SpringBoot整合RabbitMQ

七.Boot整合RabbitMQ

整合思路:
  1. 引入 spring-boot-starter-amqp
  2. 2.application.yml配置
  3. 測試RabbitMQ

​ AmqpAdmin:管理組件

​ RabbitTemplate:消息發送處理組件

1. 創建boot工程,加入rabbitmq啓動器
2. 在配置文件中加入rabbintmq 的配置信息
spring.rabbitmq.addresses=192.168.50.128
spring.rabbitmq.username=guest       
spring.rabbitmq.password=guest       
#spring.rabbitmq.virtual-host=/      
3. 使用RabbitTemplate操作rabbitMq
RabbitAutoConfiguration,ConnectionFactory,RabbitProperties自動配置;
注入RabbitTemplate:給rabbitmq發送和接收消息
AmqpAdmin: RabbitMq系統管理功能(聲明隊列,創建交換器)
4. 測試RabbitMQ的發送和接收消息
@RunWith(SpringRunner.class)
	@SpringBootTest
	public class AmqpApplicationTests {
   	//注入template模版
  	 @Autowired
  	 RabbitTemplate rt;
  	 @Test
   	public void contextLoads() {
      	//點對點發送
      	rt.convertAndSend("exchanges.direct","oracle","我是一隻小小的石頭,i am a small small stone");
      	//向fanout發送消息
      	rt.convertAndSend("exchanges.fanout","oracle","我是一隻小小的fanout,i am a small small fanout");
      	//給topic發送消息
     	 rt.convertAndSend("exchanges.topic","oracle.abc","我是一隻小小的topic,i am a small small topic");
   	}
	
  	 @Test
   	public void receive(){
      	//接收隊列的消息
     	 Object obj=rt.receiveAndConvert("oracle");
      	System.out.println(obj);
   	}
    }
/*定義一個發消息的Service*/
package com.oracle.messageService;

import com.oracle.vo.Book;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

@Service
public class OrderMessage {
    @Autowired
    RabbitTemplate rabbitTemplate;

    public void send(String message){
       Object obj= rabbitTemplate.convertSendAndReceive("amq.direct","oracle",message);
        System.out.println("結果是:"+obj);
    }


    public void send(Book book){
        Object obj= rabbitTemplate.convertSendAndReceive("order.topic","oracle.news",book);
        System.out.println("結果是:"+obj);
    }
    public void receive(){
        Object obj=rabbitTemplate.receiveAndConvert("oracle.over");
        System.out.println("obj:"+obj);
    }
}

5.配置消息轉換器

打開RabbitTemplate源碼後,找到MessageConverter類,然後在IDEA中使用ctrl+H查看到繼承關係後,找到

Jackson2JsonMessageConverter;並在配置文件中進行配置;


@Configuration
public class MessageConvertor {

    @Bean
    public MessageConverter jacksonMessageConvertor(){
        Jackson2JsonMessageConverter jackson2JsonMessageConverter=new Jackson2JsonMessageConverter();
        return  jackson2JsonMessageConverter;
    }
}
注:如果配置了消息轉換器,那麼使用@RabbitListener也需要配置相同的轉換器,否則會轉換失敗;
6.** 編寫service監聽隊列

​ @RabbitListener(queues = “oracle”)
​ 此註解放在方法上,監聽隊列

  1. 啓動類
	@EnableRabbit //啓動rabbit
	@SpringBootApplication
	public class AmqpApplication {
 		public static void main(String[] args) {
   			SpringApplication.run(AmqpApplication.class, args);
  		}
	}
  1. service類
	@Service
	public class RabbitService {
  

	@RabbitListener(queues = "oracle")
  	public void oracle(String str) {
    		System.out.println("收到了oracle隊列中的 消息:" + str);
  	}

  	@RabbitListener(queues = "book")
  	public void book(Book book){
    		System.out.println("收到一本書: "+book);
   }
}

  1. 配置類

    spring.rabbitmq.addresses=127.0.0.1
    spring.rabbitmq.username=admin
    spring.rabbitmq.password=tiger
    spring.rabbitmq.virtual-host=order
    
7.特殊說明

消息接收者和消息發送查應該使用相同的消息轉換器;默認是字節序列化。如果要改成json方式的,發送與接收到應該配置json消息轉換器;

8.管理類;
@Autowired
AmqpAdmin amqpAdmin;

@Test
public void create(){
  //創建一個exchange
  amqpAdmin.declareExchange(new DirectExchange("amqp.direct"));
  //創建一個隊列
  amqpAdmin.declareQueue(new Queue("amqp.test2"));
  //綁定交換器
  amqpAdmin.declareBinding(new Binding("amqp.test", Binding.DestinationType.QUEUE,"amqp.direct","qmqp.test",null));
}

Bingding構造方法的參數:

Amqp.test:隊列名

Binding.DestinationType.QUEUE:amqp.test的類型是隊列

Amqp.direct:exchange名稱

Qmqp.test:路由鍵

Null:叄數

操作步驟:

  1. 每執行完一個操作後,都去後臺管理去查看一下操作後的結果;
  2. 創建對象使用declaredXXX,刪除對象使用deleteXXX
  3. 通過查看源碼的方式來操作,使用ctrl+n來查找類或接口,再使用ctrl+h查看類的層次結構;

八.RabbitMQ中的消息確認ACK機制

什麼是消息確認ACK?

​ 如果在處理消息的過程中,消費者的服務器在處理消息時出現異常,那可能這條正在處理的消息就沒有完成消息消費,數據就會丟失。爲了確保數據不丟失,RabbitMQ支持消息確認,即ACK

ACK的消息確認機制

​ ACK機制是消費者從RabbitMQ收到消息並處理完成後,反饋給RabbitMQ,RabbitMQ收到反饋後纔將次消息從隊列中刪除

  1. 如果一個消費者在處理消息出現了網絡不穩定、服務器異常等現象,那麼就不會有ACK反饋,RabbitMQ會認爲這個消息沒有正常消費,會將消息重新放入隊列中
  2. 如果在集羣的情況下:RabbitMQ會立刻將這個消息推送給這個在線的其他消費者。這種機制保證了在消費者服務端故障的時候,不丟失任何消息和任務。
  3. **消息永遠不會從RabbitMQ中刪除:**只有當消費者正確返送ACK反饋,RabbitMQ確認收到後,消息纔會從RabbitMQ服務的數據中刪除。
  4. 消息的ACK確認機制默認是打開的。

ACK機制的開發注意實現

​ 如果忘記了ACK,那麼後果很嚴重。當Consumer退出時,Message會一直重新分發。然後RabbitMQ會佔用越來越多的內存,由於RabbitMQ會長時間運行,因此這個“內存泄漏”是致命的。

練習:

​ 創建兩個模塊,消費者和生產者使用direct交換器,在消費者消費消息時拋出一個RuntimeException,觀察控制檯和RabbitMQ的Web控制檯,消息會再次重新放到隊列中,執行死循環。

receiver:

@Component
@RabbitListener(bindings=@QueueBinding(
        value=@Queue(value="${mq.config.queue.info}",autoDelete = "true"),
        exchange = @Exchange(value="${mq.config.exchange}",type= ExchangeTypes.DIRECT),
        key = "${mq.config.queue.info.routing.key}"
))
public class InfoReceiver {
    @RabbitHandler
    public void process(String msg){
        System.out.println("---------consumer:receive:"+msg);
        throw new RuntimeException();
    }
}

RabbitMQ web控制檯

在這裏插入圖片描述

解決方式:

方式一:可以在消費消息中try-catch

​ 由於在消費消息時可能拋出運行時異常,這種解決方式難於處理和控制。

方式二:在Consumer的配置文件中配置重試機制

​ 配置開啓重試及重試次數,在RabbitMQ沒有收到ACK確認時,重新放入隊列,重試指定次數後不再放入隊列。

spring.application.name=mq-direct-consumer
spring.rabbitmq.host=192.168.37.151
spring.rabbitmq.port=5672
spring.rabbitmq.username=testww
spring.rabbitmq.password=000000

#開啓重試機制
spring.rabbitmq.listener.simple.retry.enabled=true
#重試次數 默認爲3次 現修改爲5次
spring.rabbitmq.listener.simple.retry.max-attempts=5
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章