RabbitMQ實戰:執行和管理RabbitMQ

情情說發表於2018-04-06

本系列是「RabbitMQ實戰:高效部署分散式訊息佇列」書籍的總結筆記。

上一篇 介紹了AMQP訊息通訊,包括佇列、交換器和繫結,通過虛擬主機還可以隔離資料和許可權,訊息持久化和傳送方確認模式確保了訊息不丟失。

本篇主要介紹如何執行和管理RabbitMQ,在介紹之前,會有個DEMO演示訊息傳送和接收,一方面對AMQP的元素有更直觀的認識,一方面為後面介紹監控做資料來源。

通過介紹,你會了解到:

  • 訊息傳送和接收簡單實現
  • 伺服器管理-啟動和停止節點
  • 許可權配置
  • 使用統計

福利傳送門:小愛音響F碼

訊息傳送和接收簡單實現

該Demo主要用於收集日誌,訊息傳送者是各個應用子系統,訊息接收者是日誌收集服務,使用RabbitMQ可以很容易實現。

基於Spring Boot框架實現,主要類的作用如下:

  • LogRabbitConfig:建立佇列、交換器、繫結等初始化操作;
  • Sender:訊息傳送者;
  • AllReceiver:所有級別日誌接收者,接收所有級別的日誌;
  • ErrorReceiver:錯誤級別日誌接受者,只接收錯誤級別的日誌;
  • LogSenderTest:測試用例類;

訊息模型如下:

Demo的訊息模型

配置

首先,配置spring boot和rabbitmq依賴:

<parent>
	<groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-parent</artifactId>
	<version>2.0.1.RELEASE</version>
	<relativePath/>
</parent>
<dependencies>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter</artifactId>
	</dependency>
	<dependency>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-test</artifactId>
		<scope>test</scope>
	</dependency>
	<!--rabbitmq依賴-->
	<dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-amqp</artifactId>
    </dependency>
</dependencies>
複製程式碼

然後在application.properties檔案中配置rabbitmq地址:

spring.rabbitmq.host=127.0.0.1
spring.rabbitmq.port=5672
spring.rabbitmq.username=guest
spring.rabbitmq.password=guest
spring.rabbitmq.publisher-confirms=true
spring.rabbitmq.virtual-host=/
複製程式碼
LogRabbitConfig實現

使用Spring的@Configuration定義配置類,可替換xml配置檔案,被註解的類內部包含有一個或多個被@Bean註解的方法,用於構建bean定義,初始化Spring容器。

@Configuration
public class LogRabbitConfig {
    final static String QUEUE_LOG_ERROR = "log.error";
    final static String QUEUE_LOG_ALL = "log.all";

    //建立log.error佇列
    @Bean
    public Queue logError() {
        return new Queue(QUEUE_LOG_ERROR);
    }
    //建立log.all佇列
    @Bean
    public Queue logAll() {
        return new Queue(QUEUE_LOG_ALL);
    }
    //建立exchange,命名為log
    @Bean
    TopicExchange exchange() {
        return new TopicExchange("log");
    }
    //繫結log.error佇列到exchange,routingkey為log.error
    @Bean
    Binding bindingExchangeError(Queue logError, TopicExchange exchange) {
        return BindingBuilder.bind(logError).to(exchange).with("log.error");
    }
    //繫結log.all佇列到exchange,routingkey為log.#
    @Bean
    Binding bindingExchangeAll(Queue logAll, TopicExchange exchange) {
        return BindingBuilder.bind(logAll).to(exchange).with("log.#");
    }
}
複製程式碼
Sender實現

各個子系統向rabbitmq伺服器傳送訊息:

@Component
public class Sender {
    @Autowired
    private AmqpTemplate rabbitTemplate;
    
    public void send() {
        //向mq服務端傳送訊息,exchange為log,routingkey為log.error
        String context = "error log";
        this.rabbitTemplate.convertAndSend("log", "log.error", context);

        //向mq服務端傳送訊息,exchange為log,routingkey為log.info
        context = "info log";
        System.out.println("send msg : " + context);
        this.rabbitTemplate.convertAndSend("log", "log.info", context);

        //向mq服務端傳送訊息,exchange為log,routingkey為log.warn
        context = "warn log";
        System.out.println("send msg : " + context);
        this.rabbitTemplate.convertAndSend("log", "log.warn", context);
    }

}
複製程式碼
AllReceiver和ErrorReceiver實現

從rabbitmq伺服器接收訊息。

AllReceiver從伺服器的log.all佇列獲取訊息,因為它繫結的routingkey為"log.#",所以,會收到所有級別的日誌:

@Component
@RabbitListener(queues = "log.all")
public class AllReceiver {
    @RabbitHandler
    public void process(String context) {
        System.out.println("receive log : " + context);
    }
}
複製程式碼

ErrorReceiver從伺服器的log.error佇列獲取訊息,因為它繫結的routingkey為"log.error",所以,只會收到error級別的日誌:

@Component
@RabbitListener(queues = "log.error")
public class ErrorReceiver {
    @RabbitHandler
    public void process(String context) {
        System.out.println("receive error : " + context);
    }
}
複製程式碼
LogSenderTest測試用例

測試用例很簡單,就是呼叫Sender傳送訊息,觀察訊息的接收情況。

@RunWith(SpringRunner.class)
@SpringBootTest
@SpringBootApplication
public class LogSenderTest {
    @Autowired
    Sender sender;

    @Test
    public void sendLog() {
        sender.send();
    }
}
複製程式碼

執行日誌如下:

執行日誌

可以看到,error收到了2次,說明exchange同時分發給了log.all和log.error佇列,其他級別的日誌分發給了log.all佇列。

伺服器管理-啟動和停止節點

RabbitMQ是用Erlang編寫的,Erlang天生就能讓應用程式無需知道對方是否在同一臺機器上即可相互通訊,這讓叢集和可靠的訊息路由變得簡單。

理解節點和Erlang應用程式

和Java有JVM虛擬機器類似,Erlang也有虛擬機器,虛擬機器的每個例項稱之為「節點」,不同的是,多個Erlang應用程式可以執行在同一個節點之上,如果應用程式崩潰了,Erlang節點會自動嘗試自動重啟應用程式。

節點的操作:

後臺啟動節點:./rabbitmq-server -detached
停止節點:./rabbitmqctl stop 
僅停止rabbit應用程式:./rabbitmqctl stop_app
複製程式碼
配置檔案

配置檔案的格式本質上是原始的Erlang資料結構,是一個包含了巢狀雜湊表的陣列,如下:

[
    [mnesia , [{dump_log_write_threshold , 1000}]],
    [rabbit , [{vm_memory_high_wateremark , 0.4}]]
]
複製程式碼

上面配置了2個應用,每個應用會有自己的雜湊表來配置選項:

  • mnesia:是rabbitmq用來儲存交換器和佇列後設資料的;
  • rabbit:是rabbitmq特定的配置選項;

每個應用如果有多個選項,用逗號隔開。

許可權配置

RabbitMQ許可權系統中,單個使用者可以跨越多個vhost進行授權,而且可以對讀、寫、配置分別授權。

首先建立一個使用者dongqingqing,密碼為123456:

./rabbitmqctl add_user dongqingqing 123456
複製程式碼

授予dongqingqing使用者許可權,可以讀取所有佇列和交換器,只可寫log.*格式的佇列和交換器,無法建立或刪除佇列和交換器

./rabbitmqctl set_permissions  dongqingqing ".*" "log.*" "" 
複製程式碼

set_permissions 後面的引數分別為使用者名稱、讀許可權、寫許可權、配置許可權。

其他詳細用法可檢視文件。

使用統計

檢視資料統計

可通過rabbitmqctl命令檢視資料統計資訊,比如佇列和訊息數目、交換器和繫結等。

檢視所有佇列,包含上面demo定義的log.all和log.error:

檢視所有佇列

檢視所有交換器,包含上面demo定義的log

檢視所有交換器

另外,rabbitmq提供了管理介面外掛,更方便的檢視各種統計,可以通過下面的命令開啟:

sudo ./rabbitmq-plugins enable rabbitmq_management
複製程式碼

rabbitmq_management外掛

檢視日誌

可以在檔案系統中檢視日誌,啟動rabbitmq後,會顯示日誌的路徑:

rabbitmq日誌路徑

另外,可以通過AMQP獲取實時日誌資訊,有一個amq.rabbitmq.log的topic交換器,監聽對應的佇列即可。

下一篇將介紹訊息通訊模式和最佳實踐,感謝大家持續關注。

歡迎掃描下方二維碼,關注我的個人微信公眾號 ~

情情說

相關文章