RabbitMQ學習及實踐2---介紹及簡單Java實現

一,基本概念

    MQ是消費-生產者模型的一個典型的代表,一端往消息隊列中不斷寫入消息,而另一端則可以讀取或者訂閱隊列中的消息。MQ和JMS類似,但不同的是JMS是SUN JAVA消息中間件服務的一個標準和API定義,而MQ則是遵循了AMQP協議的具體實現和產品。

    RabbitMQ是一個在AMQP基礎上完整的,可複用的企業消息系統。他遵循Mozilla Public License開源協議。

    RabbitMQ是流行的開源消息隊列系統,用erlang語言開發。RabbitMQ是AMQP(高級消息隊列協議)的標準實現。

1、AMQP

    模型圖如下:

wKiom1OtLOzyMd_SAAPpsOlQxcQ817.jpg

主要概念:

    Broker:簡單來說就是消息隊列服務器實體。
  Exchange:消息交換機,決定了消息路由規則,它指定消息按什麼規則,路由到哪個隊列。
  Queue:消息隊列載體,每個消息都會被投入到一個或多個隊列。
  Binding:綁定,它的作用就是把exchange和queue按照路由規則綁定起來,意即爲符合什麼樣路由規則的消息,將會放置入哪一個消息隊列。
  Routing Key:路由關鍵字,exchange根據這個關鍵字進行消息投遞。
  vhost:虛擬主機,一個broker裏可以開設多個vhost,用作不同用戶的權限分離。
  producer:消息生產者,就是投遞消息的程序。
  consumer:消息消費者,就是接受消息的程序。
  channel:進行消息讀寫的通道,在客戶端的每個連接裏,可建立多個channel,每個channel代表一個會話任務。

   

MessageQueue、Exchange和Binding構成了AMQP協議的核心,三者關係如下圖:

wKiom1OtLpTB9VkPAADrtlnTXD8245.jpg

消息隊列的使用過程大概如下:

    (1)客戶端連接到消息隊列服務器,打開一個channel。
  (2)客戶端聲明一個exchange,並設置相關屬性。
  (3)客戶端聲明一個queue,並設置相關屬性。
  (4)客戶端使用routing key,在exchange和queue之間建立好綁定關係。
  (5)客戶端投遞消息到exchange。


exchange接收到消息後,就根據消息的key和已經設置的binding,進行消息路由,將消息投遞到一個或多個隊列裏。

*Exchange是接受生產者消息並將消息路由到消息隊列的關鍵組件。ExchangeType和Binding決定了消息的路由規則。

*在RabbitMQ中,聲明一個Exchange需要三個參數:ExchangeName,ExchangeType和Durable。Durable是該Exchange的持久化屬性。

*有三種類型的Exchange:directfanouttopic,不同的Exchange會表現出不同路由行爲。

    a)如果是Direct類型,則會將消息中的RoutingKey與該Exchange關聯的所有Binding中的BindingKey進行比較,如果相等,則發送到該Binding對應的Queue中。

    b)如果是Fanout類型,則會將消息發送給所有與該 Exchange定義過Binding 的所有Queues中去,其實是一種廣播行爲。

    c)如果是Topic類型,則會按照正則表達式,對RoutingKeyBindingKey進行匹配,如果匹配成功,則發送到對應的Queue中。(符號”#”匹配一個或多個詞,符號”*”匹配正好一個詞)

    詳細解釋:

        Exchange可能bind了很多Queue,但是消息具體分到哪一個或哪一些Q呢?具體要看exchange的類型。

    具體exchange也有幾個類型:

    1、完全根據key進行投遞的叫做Direct交換機,例如,綁定時設置了routingkey爲”abc”,那麼客戶端提交的消息,只有設置了key爲”abc”的纔會投遞到隊列。

    2、對key進行模式匹配後進行投遞的叫做Topic交換機,符號”#”匹配一個或多個詞,符號”*”匹配正好一個詞。例如”abc.#”匹配”abc.def.ghi”,”abc.*”只匹配”abc.def”。

    3、還有一種不需要key的,叫做Fanout交換機,它採取廣播模式,一個消息進來時,投遞到與該交換機綁定的所有隊列。


RabbitMQ支持消息的持久化,也就是數據寫在磁盤上,爲了數據安全考慮,我想大多數用戶都會選擇持久化。消息隊列持久化包括3個部分:
  (1)exchange持久化,在聲明時指定durable => 1
  (2)queue持久化,在聲明時指定durable => 1
  (3)消息持久化,在投遞時指定delivery_mode => 2(1是非持久化)

如果exchange和queue都是持久化的,那麼它們之間的binding也是持久化的。如果exchange和queue兩者之間有一個持久化,一個非持久化,就不允許建立綁定。


AMQP協議可參考以下文章:http://blog.chinaunix.net/uid-22312037-id-3458208.html


2、簡單實現

    一下爲java的簡單實現:

客戶端:

import com.rabbitmq.client.Channel;
import com.rabbitmq.client.Connection;
import com.rabbitmq.client.ConnectionFactory;
public class Send {
  private final static String QUEUE_NAME = "hello";
    public static void main(String[] args) throws.IOException{
  ConnectionFactory factory = new ConnectionFactory();
  factory.setHost("localhost");
  Connection connection = factory.newConnection();
  Channel channel = connection.createChannel();
  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();
  }
}

消費者端:

public class RabbitMQRecv {
  private final static String QUEUE_NAME = "hello";
    public static void main(String avg[]) throws.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");
  QueueingConsumer consumer = new QueueingConsumer(channel);
  channel.basicConsume(QUEUE_NAME, true, consumer);
  while (true) {
      QueueingConsumer.Delivery delivery = consumer.nextDelivery();
      String message = new String(delivery.getBody());
      System.out.println(" [x] Received '" + message + "'");
  }
  }
}
*通過設置Exchange和MessageQueue的durable屬性爲true,可以使得隊列和Exchange持久化;
*生產者在發送消息的時候,將deliverymode設置爲MessageProperties.PERSISTENT_TEXT_PLAIN;
*durable爲true的Exchange和durable爲ture的Queues才能綁定,否則在綁定時,RabbitMQ都會拋錯的。
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章