SpringBoot集成RabbitMQ高級使用

 

1.交換器

發消息者、隊列、收消息者,RabbitMQ 在這三個基本概念之上, 做了一層抽象, 在發消息者和 隊列之間, 加入了交換器 (Exchange). 這樣發消息者和隊列就沒有直接聯繫, 轉而變成發消息者把消息給交換器, 交換器根據調度策略再把消息再給隊列。

                                               

P 代表生產者,X代表交換器,後邊是隊列,C代表消費者。

其中中間一層server可以稱爲虛擬主機。

  • 虛擬主機:一個虛擬主機持有一組交換機、隊列和綁定。爲什麼需要多個虛擬主機呢?很簡單,RabbitMQ當中,用戶只能在虛擬主機的粒度進行權限控制。 因此,如果需要禁止A組訪問B組的交換機/隊列/綁定,必須爲A和B分別創建一個虛擬主機。每一個RabbitMQ服務器都有一個默認的虛擬主機“/”。

  • 交換機:Exchange 用於轉發消息,但是它不會做存儲 ,如果沒有 Queue bind 到 Exchange 的話,它會直接丟棄掉 Producer 發送過來的消息。
    這裏有一個比較重要的概念:路由鍵 。消息到交換機的時候,交互機會轉發到對應的隊列中,那麼究竟轉發到哪個隊列,就要根據該路由鍵。

  • 綁定:也就是交換機需要和隊列相綁定,這其中如上圖所示,是多對多的關係

    交換機的功能主要是接收消息並且轉發到綁定的隊列,交換機不存儲消息,在啓用ack模式後,交換機找不到隊列會返回錯誤。交換機有四種類型:Direct, topic, Headers and Fanout

  • Direct:direct 類型的行爲是”先匹配, 再投送”. 即在綁定時設定一個 routing_key, 消息的routing_key 匹配時, 纔會被交換器投送到綁定的隊列中去.

  • Topic:按規則轉發消息(最靈活)

  • Headers:設置header attribute參數類型的交換機

  • Fanout:轉發消息到所有綁定隊列

代碼實現

Topic模式

新建兩個queue和一個topic交換器,並且,兩個隊列綁定到交換器上。

package com.haval.demo.mq;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
@Configuration
public class TopicRabbitConfig {
	final static String message = "topic.queue";  
    final static String messages = "topic.queues";
    @Bean
    public Queue queueMessage() {        
       return new Queue(TopicRabbitConfig.message);
    }
    @Bean
    public Queue queueMessages() {        
       return new Queue(TopicRabbitConfig.messages);
    }
    @Bean
    TopicExchange exchange() {        
       return new TopicExchange("exchange");
    }
    @Bean
    Binding bindingExchangeMessage(Queue queueMessage, TopicExchange exchange) {        
       return BindingBuilder.bind(queueMessage).to(exchange).with("topic.queue");
    }
    @Bean
    Binding bindingExchangeMessages(Queue queueMessages, TopicExchange exchange) {        
       return BindingBuilder.bind(queueMessages).to(exchange).with("topic.#");
    }
}

然後定義兩個消息發送的方法

public void sendMessage() {
    	for (int i = 0; i < 100; i++) {
        	String context = "Message " + new Date()+"-------"+String.valueOf(i);
            System.out.println("Sender : " + context);
        	this.rabbitTemplate.convertAndSend("exchange",TopicRabbitConfig.message, context);
    	}
        
    }
    public void sendMessages() {
    	for (int i = 0; i < 100; i++) {
    		String context = "Messages " + new Date()+"---s----"+String.valueOf(22);
            System.out.println("Sender : s " + context);
        	this.rabbitTemplate.convertAndSend("exchange",TopicRabbitConfig.messages, context);
		}
        	
    }

然後定義兩個,隊列的監聽器

@Component
@RabbitListener(queues = TopicRabbitConfig.message)
public class TopicMessageReceiver {
	@RabbitHandler
    public void process(String hello) {
        System.out.println("我是處理消息的111" + hello);
    }
}


@Component
@RabbitListener(queues = TopicRabbitConfig.messages)
public class TopicMessagesReceiver {
	@RabbitHandler
    public void process(String hello) {
		 System.out.println("我是處理消息的222" + hello);
    }
}

當執行sendMessage()的時候,兩個隊列都能收到消息,當執行sendMessages()的時候,只有queues能收到消息。

Fanout Exchange就是發佈和訂閱模式,給Fanout交換機發送消息,綁定了這個交換機的所有隊列都收到這個消息。

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.amqp.core.Binding;
import org.springframework.amqp.core.BindingBuilder;
import org.springframework.amqp.core.FanoutExchange;
import org.springframework.amqp.core.Queue;
import org.springframework.amqp.core.TopicExchange;
@Configuration
public class FanoutRabbitConfig {
	final static String Fanoutqueue1 = "Fanout.queue1";  
    final static String Fanoutqueue2 = "Fanout.queue2";
    final static String Fanoutqueue3 = "Fanout.queue3";
    @Bean
    public Queue Fanoutqueue1() {        
       return new Queue(FanoutRabbitConfig.Fanoutqueue1);
    }
    @Bean
    public Queue Fanoutqueue2() {        
       return new Queue(FanoutRabbitConfig.Fanoutqueue2);
    }
    @Bean
    public Queue Fanoutqueue3() {        
       return new Queue(FanoutRabbitConfig.Fanoutqueue3);
    }
    @Bean
    public FanoutExchange FanoutExchange() {        
       return new FanoutExchange("FanoutExchange");
    }
    @Bean
    Binding bindingExchange1(Queue Fanoutqueue1, FanoutExchange FanoutExchange) {        
       return BindingBuilder.bind(Fanoutqueue1).to(FanoutExchange);
    }
    @Bean
    Binding bindingExchange2(Queue Fanoutqueue2, FanoutExchange FanoutExchange) {        
       return BindingBuilder.bind(Fanoutqueue2).to(FanoutExchange);
    }
    @Bean
    Binding bindingExchange3(Queue Fanoutqueue3, FanoutExchange FanoutExchange) {        
       return BindingBuilder.bind(Fanoutqueue3).to(FanoutExchange);
    }
}
public void sendFanout(){
	        String context = "hi, fanout msg ";
	        System.out.println("Sender : " + context);       
	        this.rabbitTemplate.convertAndSend("FanoutExchange","", context);
	}

在綁定三個監聽器

@Component
@RabbitListener(queues = FanoutRabbitConfig.Fanoutqueue1)
public class FanoutMessageReceiver1 {
	@RabbitHandler
    public void process(String hello) {
        System.out.println("我是處理消息的1" + hello);
    }
}
Sender : hi, fanout msg 
我是處理消息的1hi, fanout msg 
我是處理消息的2hi, fanout msg 
我是處理消息的3hi, fanout msg 

三個隊列都會收到消息

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