RabbitMQ | 基礎

參看連接:java

springboot(八):RabbitMQ詳解--Author@純潔的微笑spring

一、sender,queue,receiver

隊列服務有三個概念: 發消息者、隊列、收消息者。springboot

  • 左側 P 表明 生產者,也就是往 RabbitMQ 發消息的程序。
  • 中間 RabbitMQ,其中包括了 交換機 X 和 隊列 Q。
  • 右側 C 表明 消費者,也就是往 RabbitMQ 拿消息的程序。

比較重要的概念有 4 個:虛擬主機,交換機,隊列和綁定。bash

  • 虛擬主機:一個虛擬主機持有一組交換機、隊列和綁定。爲何須要多個虛擬主機呢?很簡單,RabbitMQ當中,用戶只能在虛擬主機的粒度進行權限控制。 所以,若是須要禁止A組訪問B組的交換機/隊列/綁定,必須爲A和B分別建立一個虛擬主機。每個RabbitMQ服務器都有一個默認的虛擬主機「/」。
  • 交換機:Exchange 用於轉發消息,可是它不會作存儲 ,若是沒有 Queue bind 到 Exchange 的話,它會直接丟棄掉 Producer 發送過來的消息。 這裏有一個比較重要的概念:路由鍵 。消息到交換機的時候,交互機會轉發到對應的隊列中,那麼究竟轉發到哪一個隊列,就要根據該路由鍵。
  • 綁定:也就是交換機須要和隊列相綁定,這其中如上圖所示,是多對多的關係。

二、交換機(Exchange)

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

  • Direct:direct 類型的行爲是"先匹配, 再投送". 即在綁定時設定一個 routing_key, 消息的routing_key 匹配時, 纔會被交換器投送到綁定的隊列中去.
  • Topic:按規則轉發消息(最靈活)
  • Headers:設置header attribute參數類型的交換機
  • Fanout:轉發消息到全部綁定隊列

2.一、Direct Exchange

Direct Exchange是RabbitMQ默認的交換機模式,也是最簡單的模式,根據key全文匹配去尋找隊列。app

第一個 X - Q1 就有一個 binding key,名字爲 orange; X - Q2 就有 2 個 binding key,名字爲 black 和 green。當消息中的 路由鍵 和 這個 binding key 對應上的時候,那麼就知道了該消息去到哪個隊列中。 spring-boot

2.二、Topic Exchange

Topic Exchange 轉發消息主要是根據通配符。 在這種交換機下,隊列和交換機的綁定會定義一種路由模式,那麼,通配符就要在這種路由模式和路由鍵之間匹配後交換機才能轉發消息。 在這種交換機模式下:測試

  • 路由鍵必須是一串字符,用句號(.) 隔開:如 agreements.us, agreements.eu.stockholm  
  • 路由模式必須包含一個 星號(*),主要用於匹配路由鍵指定位置的一個單詞,好比說,一個路由模式是這樣子:agreements..b.*,那麼就只能匹配路由鍵是這樣子的:第一個單詞是 agreements,第四個單詞是 b。 井號(#)就表示至關於一個或者多個單詞,例如一個匹配模式是agreements.eu.berlin.#,那麼,以agreements.eu.berlin開頭的路由鍵都是能夠的。

具體代碼發送的時候仍是同樣,第一個參數表示交換機,第二個參數表示routing key,第三個參數即消息。以下:this

rabbitTemplate.convertAndSend("testTopicExchange","key1.a.c.key2", " this is RabbitMQ!");

topic 和 direct 相似, 只是匹配上支持了"模式", 在"點分"的 routing_key 形式中, 可使用兩個通配符:spa

  • *表示一個詞.
  • #表示零個或多個詞.

2.三、Headers Exchange

headers 也是根據規則匹配, 相較於 direct 和 topic 固定地使用 routing_key , headers 則是一個自定義匹配規則的類型. 在隊列與交換器綁定時, 會設定一組鍵值對規則, 消息中也包括一組鍵值對( headers 屬性), 當這些鍵值對有一對, 或所有匹配時, 消息被投送到對應隊列.

2.四、Fanout Exchange

Fanout Exchange 消息廣播的模式,無論路由鍵或者是路由模式,會把消息發給綁定給它的所有隊列,若是配置了routing_key會被忽略。

三、In Action

3.1 springboot集成rabbitmq(Hello World)

經過start.spring.io生成含有spring-boot-starter-amqp依賴的項目,結構以下:

application.properties

spring.application.name=DdoubleRabbit
debug=true

spring.rabbitmq.host=localhost
spring.rabbitmq.port=5672
spring.rabbitmq.username=ddouble
spring.rabbitmq.password=Tong2014

RabbitConfig.java

package com.ddouble.DdoubleRabbit.rabbit;

import org.springframework.amqp.core.Queue;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class RabbitConfig {
    @Bean
    public Queue helloQueue() {
        return new Queue("hello");
    }
}

HelloSender.java

package com.ddouble.DdoubleRabbit.rabbit.hello;

import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.util.Date;

@Component
public class HelloSender {
    @Autowired
    private AmqpTemplate rabbitTemplate;

    public void send() {
        String context = "hello" + new Date();
        System.out.println("Sender : " + context);
        this.rabbitTemplate.convertAndSend("hello", context);
    }
}

HelloReceiver.java

package com.ddouble.DdoubleRabbit.rabbit.hello;

import org.springframework.amqp.rabbit.annotation.RabbitHandler;
import org.springframework.amqp.rabbit.annotation.RabbitListener;
import org.springframework.stereotype.Component;

@Component
@RabbitListener(queues = "hello")
public class HelloReceiver {
    @RabbitHandler
    public void process(String str) {
        System.out.println("Receiver : " + str);
    }
}

測試類

package com.ddouble.DdoubleRabbit;

import com.ddouble.DdoubleRabbit.rabbit.hello.HelloSender;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;

@RunWith(SpringRunner.class)
@SpringBootTest
public class DdoubleRabbitApplicationTests {
	@Autowired
	private HelloSender helloSender;

	@Test
	public void contextLoads() {
		helloSender.send();
	}
}

控制檯打印:

RabbitMQ能夠看到一個「hello」的Queue

相關文章
相關標籤/搜索