1.Hello World#前山翻譯

注:這是RabbitMQ-java版Client的指導教程翻譯系列文章,歡迎大家批評指正
第一篇Hello Word了解RabbitMQ的基本用法
第二篇Work Queues介紹隊列的使用
第三篇Publish/Subscribe介紹轉換器以及其中fanout類型
第四篇Routing介紹direct類型轉換器
第五篇Topics介紹topic類型轉換器
第六篇RPC介紹遠程調用

預備條件
這篇指導教程的前提是已經下載了RabbitMQ并且運行在本機上默認端口號5672。如果你使用不同的主機,端口號或者相關認證,連接設置需要做一些調整。
尋求幫助
如果你在閱讀這個系列指導教程時有任何的問題,可以通過郵件聯系我們

介紹(Introduction)

RabbitMQ是一個消息中間件:它接受并轉發消息。你可以把它看成是一個郵局:當你把想投遞的郵件放在郵箱中時,知道郵遞員終會把郵件派送給收件人。這個比喻中,RabbitMQ是郵箱,郵局和郵遞員。

RabbitMQ和郵局之間最大的不同是前者不需要處理紙張,就可以接受,存儲并且傳發二進制數據的消息。

通常,RabbitMQ和消息傳送會有一些專業術語。

生產和發送的意義是一樣的,一個應用發送消息就是生產者:

producer.png

隊列類似郵局中的郵箱存在于RabbitMQ中,盡管消息是在RabbitMQ和應用間傳送,但消息只存儲在隊列中。隊列的大小只受限于主機的內存或者硬盤的大小,本質上是有無限大的緩存區間。許多生產者可以發送消息到一個隊列中,當然需要消費者也可以從一個隊列中接受消息。我們用下列圖形代表隊列:

queue.png

消費和接受有著同樣的意思,一個應用常在等待接受消息就是消費者:
consumer.png

注解:生產者,消費者以及消息中間件并不會存在于同一個主機上,且大部分應用確實也不會這樣做。

"Hello World"

(using the java Client ,我是搞Android開發的,所以語言沒得選:java是當今世界上最流行的語言)

在這篇指導教程中,我們將用Java寫兩個應用,發送一條簡單消息的生產者,和接受消息并且將消息打印出來的消費者。我們將會省略掉部分Java API的具體細節,專注于開始學習最簡單的"Hello World"消息傳遞。

在下面的圖表中,"P"表示生產者和"C"表示消費者,中間的盒子表示隊列-消費者的消息緩存在RabbitMQ中。

java_one.png

MabbitMQ的java版本客戶端的依賴包(The Java Client library)
RabbitMQ支持多種協議,這篇指導教程中使用AMQP協議,這是一個開源,多用途的消息傳遞協議。針對不同的語言,RabbitMQ提供專門的客戶端版本,目前我們使用的是Java版本。
下載Java Client library并且依賴于SLF4J APISLF4J Simple,拷貝這些文件到你的工作目錄下,跟其它的java文件一塊放。
請注意SLF4J Simple只是在指導教程中使用,而在真正的生產項目中,應該使用更強大的日志包,像Logback。
現在我們有了Java版本的客戶端RabbitMQ和依賴包,可以寫些代碼了。

發送(Sending)

sending.png

我們將稱消息發布者(發送者)為Send,消息消費者(接受者)為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 java.io.IOException {

      ...

    }

}

接著我們連接服務端:

ConnectionFactory factory = new ConnectionFactory();

factory.setHost("localhost");  //factory可以設置主機Ip,端口號,認證信息等連接服務端

Connection connection = factory.newConnection();  //創建連接

Channel channel = connection.createChannel();  //創建通道

這是抽象的Socket(套接宇)連接方式,注意協議版本的差異和驗證等等都取決于我們自己。我們連接到本機的RabbitMQ上,所以才是localhost。如果我們想連接到不同的機器上的RabbitMQ上,可以簡單說明該機器的名稱和IP地址。(下面代碼是我擅自添加的)

factory.setPort(8080);

factory.setUsername("admin");

factory.setPassword("password"):

下一步創建通道(channel),大部分的事情都是在這里處理。

我們必須先聲明發送消息去的隊列,然后發送消息到隊列中:

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 + "'");

聲明隊列是很重要的,它不存在時才會被創建,消息體是字節數組類型,因此可以在這里編碼你需要的類型。
最后,關閉通道和連接:

channel.close();
connection.close();

這里是Send.java的源碼(這么簡答的代碼,不想貼)

發送失敗

如果這是你第一次使用RabbitMQ,并且你沒有看到發送的消息,可能傷腦筋了:哪里出了問題?可能是消息中間件開始的時候可用硬盤空間不足(默認的至少剩余200MB),因此會拒絕接收消息。查看消息中間件的日志文件和如果有必要的話減少這些限制。這篇配置文檔將會告訴你如何去設置硬盤剩余空間的限制。

接受(Receiving)

發布者相對應的就是我們的接受者,接受者是接受從RabbitMQ推送過來的消息,而不像發布者是發布消息到RabbitMQ中。我們設置了對消息的監聽,并且打印出消息:


receiving.png

Recv.java的引入類和Send.java有三個是一樣的:

import com.rabbitmq.client.ConnectionFactory;

import com.rabbitmq.client.Connection;

import com.rabbitmq.client.Channel;

import com.rabbitmq.client.Consumer;

import com.rabbitmq.client.DefaultConsumer;

這個額外的DefaultConsumer是一個實現了Consumer接口的類,我們用來緩存由服務端推送給接受者的消息。

和發布者開始的創建是類似的,打開連接(connection)和通道(channel),并且聲明一條可以消費消息的隊列。注意這個隊列是匹配send發布消息的隊列:

public class Recv {

    private final static String QUEUE_NAME = "hello";

    public static void main(String[] argv)  throws  java.io.IOException,  java.lang.InterruptedException {

        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");

        ...

    }

}

請注意消費者也聲明了隊列,因為我們可以在創建發布者之前先創建消費者。我們像確保這些隊列已經存在了,然后就可以從隊列中消費消息。

將要告訴 服務端要從隊列中分發消費者的消息,然后就會異步的推送消息給消費者。我們提供了一個callBack的表單對象用于緩存消息直到消費者已經獲取到它們。這個就是DefaultConsumer子類的工作:

Consumer consumer = new DefaultConsumer(channel) {

    @Override

    public void handleDelivery(String consumerTag, Envelope envelope,AMQP.BasicProperties properties, byte[] body)  throws IOException {

        String message = new String(body, "UTF-8");

        System.out.println(" [x] Received '" + message + "'");

   }

};

    channel.basicConsume(QUEUE_NAME, true, consumer);

綜合

你可以在RabbitMQ java客戶端編譯這些類:

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

在一個終端上運行消費者,你需要rabbitmq-client.jar和一些依賴:

java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Recv

接著運行生產者:

java -cp .:amqp-client-4.0.2.jar:slf4j-api-1.7.21.jar:slf4j-simple-1.7.22.jar Send

在Windows系統上,使用分好代替冒號去分割每一個條目。
通過RabbitMQ,消費者將會打印出從生產者接受的消息,并且一直運行等待著接受消息(可以使用Ctrl +C去停止運行),因此可以嘗試從另外一個終端來運行生產者。

第一節的內容大致翻譯完了,這里是原文的鏈接。接著進入下一節:Work Queues

終篇是我對RabbitMQ使用理解的總結文章,歡迎討教。
--謝謝--

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,981評論 19 139
  • 來源 RabbitMQ是用Erlang實現的一個高并發高可靠AMQP消息隊列服務器。支持消息的持久化、事務、擁塞控...
    jiangmo閱讀 10,408評論 2 34
  • 關于消息隊列,從前年開始斷斷續續看了些資料,想寫很久了,但一直沒騰出空,近來分別碰到幾個朋友聊這塊的技術選型,是時...
    預流閱讀 585,488評論 51 786
  • 在我的少年時代,看電影可是一件天大的事兒。 那時候,一個公社(大體上相當于現在的一個鄉鎮,在管轄范圍上甚至還要更大...
    唐風漢韻1970閱讀 119評論 17 16
  • 問答 一、Jquery 中, $(document).ready()是什么意思?和window.onload 的區...
    咩咩咩1024閱讀 249評論 0 1