深入淺出 RabbitMQ

wh7577發表於2021-09-09

什麼是 RabbitMQ

簡介(優點)

  • 基於 ErLang 語言開發有高可用高併發的優點,適合叢集。

  • 開源、穩定、易用、跨平臺、支援多種語言、文件齊全。

  • 有訊息確認機制和持久化機制,可靠性高。

概念

生產者和消費者

  • Producer:訊息的生產者

  • Consumer:訊息的消費者

Queue

  • 訊息佇列提供了 FIFO 的處理機制,具有快取訊息的能力。在 RabbitMQ 中,佇列訊息可以設定為持久化,臨時或者自動刪除。

  • 如果是持久化的佇列,Queue 中的訊息會在 Server 本地硬碟儲存一份,防止系統 Crash 資料丟失。

  • 如果是臨時的佇列,Queue 中的資料在系統重啟之後就會丟失。

  • 如實是自動刪除的佇列,當不存在使用者連線到 Server,佇列中的資料會被自動刪除。

ExChange

ExChange 類似於資料通訊網路中的交換機,提供訊息路由策略。

RabbitMQ 中,生產者不是將訊息直接傳送給 Queue,而是先傳送給 ExChangeExChange 根據生產者傳遞的 key 按照特定的路由演算法將訊息給指定的 Queue。一個 ExChange 可以繫結多個 Queue。和 Queue 一樣,ExChange 也可以設定為持久化、臨時或者自動刪除。

Binding

所謂繫結就是將一個特定的 ExChange 和一個特定的 Queue 繫結起來。ExChangeQueue 的繫結可以是多對多的關係。

Virtual Host

RabbitMQ Server上可以建立多個虛擬的 Message Broker(又叫做 Virtual Hosts)。每一個 vhost 本質上是一個迷你的 RabbitMQ Server,分別管理各自的 ExChangebinding。生產者和消費者連線 RabbitMQ Server 需要指定一個 Virtual Host

使用過程

  1. 客戶端連線到訊息佇列伺服器,開啟一個 Channel

  2. 客戶端宣告一個 ExChange,並設定相關屬性。

  3. 客戶端宣告一個 Queue,並設定相關屬性。

  4. 客戶端使用 Routing Key,在 ExChangeQueue 之間建立好繫結關係。

  5. 客戶端投遞訊息到 ExChange

  6. ExChange 接收到訊息後,就根據訊息的 key 和已經設定的 bingding,進行訊息路由,將訊息投遞到一個或多個佇列裡。

部署 RabbitMQ

使用 Docker Compose 部署

建立 docker-compose.yml

version: '3.1’
services:
rabbitmq:
restart: always
image: rabbitmq:management
container_name: rabbitmq
ports:

  • 5672:5672
  • 15672:15672
    environment:
    TZ: Asia/Shanghai
    RABBITMQ_DEFAULT_USER: rabbit
    RABBITMQ_DEFAULT_PASS: 123456
    volumes:
  • ./data:/var/lib/rabbitmq

RabbitMQ WebUI 介面

  • 訪問地址:

  • 首頁

    圖片描述

  • Global counts

    圖片描述.png)

  • 交換機頁

    圖片描述.png)

  • 佇列頁

    圖片描述.png)

    • Name:訊息佇列的名稱,這裡是透過程式建立的

    • Features:訊息佇列的型別,durable:true 為會持久化訊息

    • Ready:準備好的訊息

    • Unacked:未確認的訊息

    • Total:全部訊息

      如果都為 0 則說明全部訊息處理完成

使用 RabbitMQ

建立生產者

建立一個名為 spring-boot-amqp-provider 的生產者專案。

相關配置

  • 建立 application.yml 檔案

    spring:
    application:
    name: spring-boot-amqp
    rabbitmq:
    host: 192.168.75.133
    port: 5672
    username: rabbit
    password: 123456

  • 建立佇列

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


    @Configuration
    public class RabbitMQConfiguration {

@Bean
public Queue queue() {
return new Queue(“helloRabbitMQ”);
}
}

  • 建立訊息提供者

    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 RabbitMQProvider {

  • @Autowired
    private AmqpTemplate amqpTemplate;

    public void send() {
    String context = “hello” + new Date();
    System.out.println("Provider: " + context);
    amqpTemplate.convertAndSend(“helloRabbitMQ”, context);
    }
    }

    傳送訊息

    建立測試用例

    import com.lusifer.spring.boot.amqp.Application;
    import com.lusifer.spring.boot.amqp.provider.HelloRabbitProvider;
    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(classes = Application.class)
    public class AmqpTest {

    @Autowired
    private HelloRabbitProvider helloRabbitProvider;

    @Test
    public void testSender() {
    for (int i = 0; i < 10; i++) {
    RabbitMQProvider.send();
    }
    }
    }

    建立消費者

    建立一個名為 spring-boot-amqp-consumer 的消費者專案。

    相關配置

    建立 application.yml 檔案

    spring:
    application:
    name: spring-boot-amqp-consumer
    rabbitmq:
    host: 192.168.75.133
    port: 5672
    username: rabbit
    password: 123456

    接收訊息

    建立訊息的消費監聽元件

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

    @Component
    @RabbitListener(queues = “helloRabbitMQ”)
    public class HelloRabbitConsumer {

    @RabbitHandler
    public void process(String message) {
    System.out.println("Consumer: " + message);
    }
    }

    • 文章作者:彭超

    • 本文首發於個人部落格:

    • 版權宣告:本部落格所有文章除特別宣告外,均採用 CC BY-NC-SA 4.0 許可協議。轉載請註明來自 !

    來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2480/viewspace-2825868/,如需轉載,請註明出處,否則將追究法律責任。