RabbitMQ教程 1.「Hello World」

消息隊列做爲開發中經常使用的中間件,主要應用於處理削峯、異步、解耦等場景。RabbitMQ因其使用簡單,配置靈活,管理方便而廣受使用。爲了方便小白快速入門,課表明翻譯了官方教程原文供你們參考,如下爲其第一篇:「Hello World」

1 "Hello World"

介紹java

RabbitMQ 是一個消息代理(message broker):它接收並轉發消息。你能夠把它想象成郵局,當你把要發送的信件放到郵箱裏時,你能夠確信某位郵遞員最終會將你的信件投遞給接收人。在這個類比中,RabbitMQ 就是郵箱+郵局+郵遞員git

RabbitMQ 和郵局的主要區別是,它不處理紙質信件,取而代之的是,它接收、存儲並轉發二進制數據——消息(message)github

RabbitMQ 和消息投遞中,用到了以下術語:編程

  • 生產(Producing)就是發送。發送消息的程序就是生產者:

生產(Producing)

  • 隊列就是 RabbitMQ 裏的郵箱。儘管消息從 RabbitMQ 流向你的應用,但消息只能存儲在隊列中。隊列受限於宿主機的內存和硬盤大小,它的本質是一個巨大的消息緩衝。生產者們能夠發送消息給隊列,消費者們能夠從隊列接收消息。隊列可用下圖表示:

隊列(Queue)

  • 消費(Consuming )就是接收消息。消費者是等待接收消息的程序:

生產者,消費者和消息代理不必在同一臺主機上,實際上在大多數應用場景中,三者都在不一樣的機器上。一個應用既能夠是生產者,也能夠是消費者。segmentfault

"Hello World"

(Java 代碼實現)api

在這部分教程中,咱們將會編寫兩個 Java 應用:生產者用於發送單條消息,消費者用於接收消息並打印收到的消息。咱們將會詳細介紹幾個 Java API,用於實現這個簡單的功能。這就是消息發送界的 "Hello World"。數組

下圖中,「P」是生產者,「C」是消費者,中間的紅框是隊列——RabbitMQ 爲消費者提供的消息緩衝區。緩存

Producer-queue-Consumer

Java庫服務器

RabbitMQ 支持多種協議,本教程使用 AMQP 0-9-1,它是開源、通用的消息發送協議。RabbitMQ的客戶端支持多種編程語言。本文使用 RabbtiMQ 提供的Java 客戶端。異步

下載相應 Java 庫和相關依賴 (SLF4J APISLF4J Simple)。把文件複製到工做目錄中。

須要注意的是, SLF4J Simple 僅用於教程演示,生產環境請使用全功能日誌記錄類庫,如: Logback

(RabbitMQ 的 Java 客戶端也在Maven 倉庫中提供,groupId:com.rabbitmq,artifactId:amqp-client)

如今有了 Java 客戶端和依賴庫,能夠寫點代碼了。

發送(Sending)

咱們把消息發佈者(sender) 類命名爲 Send,消息消費者(receiver)命名爲Recv。發佈者將會鏈接到 RabbitMQ,發送一條消息,而後退出。

Send.java 中,須要引入以下類:

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.Channel;

編寫類代碼給隊列命名:

public class Send {
  private final static String QUEUE_NAME = "hello";
  public static void main(String[] argv) throws Exception {
      ...
  }
}

而後鏈接到服務器

ConnectionFactory factory = new ConnectionFactory();
factory.setHost("localhost");
try (Connection connection = factory.newConnection();
     Channel channel = connection.createChannel()) {
     
}

Connection 類封裝了socket 鏈接,並替咱們處理協議版本協商和認證等工做。這裏咱們鏈接到了本機的RabbitMQ 節點——由於鏈接地址寫的是 localhost

若是想鏈接到其餘機器節點,只須要指定主機名或者IP地址便可。

接下來建立 channel,API 的全部工做都依賴於 channel 完成。因爲 Connectionchannel 都實現了java.io.Closeable,咱們可使用 try-with-resource 語句,防止顯式編寫關閉代碼。

要發送消息,須要聲明一個隊列(queue)做爲目標;而後把消息發送給這個隊列,全部代碼能夠寫到 try-with-resource 語句中

channel.queueDeclare(QUEUE_NAME, false, false, false, null);
String message = "Hello World!";
channel.basicPublish("", QUEUE_NAME, null, message.getBytes());
System.out.println(" [x] Sent '" + message + "'");

聲明隊列操做是冪等的——也就是說只有當聲明的隊列不存在時纔會建立。消息內容是字符數組,從而能夠對任意內容進行編碼。

點擊查看 Send.java 源文件

接收(Receiving)

上面介紹的是發佈者。咱們的消費者要從 RabbitMQ 監聽消息,與發佈者每次發送單個消息不一樣,消費者會一直運行並監聽消息,而後把監聽到的消息打印出來。

接收(Receiving)

Recv.java 中的引用 和 Send同樣:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.DeliverCallback;

咱們將使用DeliverCallback接口來緩存服務端發給咱們的消息。

配置代碼和發佈者同樣:建立connectionchannel,聲明須要從哪一個隊列(queue)消費消息。這裏要和發佈者的 queue 相對應。

public class Recv {

  private final static String QUEUE_NAME = "hello";

  public static void main(String[] argv) throws Exception {
    ConnectionFactory factory = new ConnectionFactory();
    factory.setHost("localhost");
    Connection connection = factory.newConnection();
    Channel channel = connection.createChannel();

    channel.queueDeclare(QUEUE_NAME, false, false, false, null);
    System.out.println(" [*] Waiting for messages. To exit press CTRL+C");

  }
}

注意這裏咱們也聲明瞭隊列。由於咱們可能在運行發佈者以前,先運行生產者,這樣寫是爲了確保消費消息時,相應隊列存在。

爲何不用 try-with-resource 語句來自動關閉channelconnection 呢?若是這樣寫,至關於讓程序繼續往下執行,關閉全部資源而後退出應用!而咱們的目的是但願應用一直存活,持續地異步監聽消息。

接下來咱們將告知服務器將 queue 裏的消息發送過來。因爲服務器異步給咱們推送消息,咱們提供一個對象形式的回調用來緩存消息,直到消息可用。這就是DeliverCallback子類的做用

DeliverCallback deliverCallback = (consumerTag, delivery) -> {
    String message = new String(delivery.getBody(), "UTF-8");
    System.out.println(" [x] Received '" + message + "'");
};
channel.basicConsume(QUEUE_NAME, true, deliverCallback, consumerTag -> { });

點擊查看 Recv.java 源文件

代碼整合(Putting it all together)

只須要把 RabbitMQ java 客戶端代碼放在 classpath下,你就能夠編譯這倆文件:

javac -cp amqp-client-5.7.1.jar Send.java Recv.java

爲了運行他們,你須要 rabbitmq-client.jar 和它的依賴包。在終端中運行消費者(receiver):

java -cp .:amqp-client-5.7.1.jar:slf4j-api-1.7.26.jar:slf4j-simple-1.7.26.jar Recv

而後運行發佈者(sender):

java -cp .:amqp-client-5.7.1.jar:slf4j-api-1.7.26.jar:slf4j-simple-1.7.26.jar Send

Windows 系統下,類路徑中的項目分隔符使用分號取代冒號。

消費者將會打印出經過 RabbitMQ 獲取到的發佈者所發佈的消息。消費者程序將會持續運行,等待接收消息(使用ctrl+c 中止),所以,能夠再開一個終端來運行發送者。

列出隊列

你可能想知道 RabbitMQ 有哪些隊列(queue),每一個隊列裏有多少消息。

能夠經過 rabbitmqctl 工具查看:

sudo rabbitmqctl list_queues

Windows系統下省略 sudo:

rabbitmqctl list_queues

接下來咱們學習第二部分,創建一個簡單的工做隊列。

小提示

爲了縮短命令,能夠給這些類路徑設置環境變量

export CP=.:amqp-client-5.7.1.jar:slf4j-api-1.7.26.jar:slf4j-simple-1.7.26.jar
java -cp $CP Send

Windows下:

set CP=.;amqp-client-5.7.1.jar;slf4j-api-1.7.26.jar;slf4j-simple-1.7.26.jar
java -cp %CP% Send

推薦閱讀

Freemarker 教程(一)-模板開發手冊

下載的附件名總亂碼?你該去讀一下 RFC 文檔了!


碼字不易,歡迎點贊分享。
搜索:【Java課表明】,關注公衆號,及時獲取更多Java乾貨。

相關文章
相關標籤/搜索