1. 程式人生 > >使用AMQP實現訊息功能---RabbitMQ

使用AMQP實現訊息功能---RabbitMQ

實際上,AMQP具有多項JMS所不具備的優勢。首先,AMQP為訊息定義了線路層的協議。AMQP在互相協作方面就要優於JMS—它不僅能跨不同的AMQP實現,還能跨語言和平臺。AMQP能夠不侷限於java平臺和語言。

1. AMQP簡介
在JMS訊息中主要有三個參與者:訊息的生產者,訊息的消費者以及消費者和生產者之間傳遞的通道。在JMS中,通道有助於解耦訊息的生產者和消費者,但是這兩者依然會與通道相耦合。
在使用AMQP的生產者並不會直接將訊息發不到佇列中。AMQP在訊息的生產者以及傳遞訊息的佇列之間引入了一種間接的機制:Exchange。這樣,訊息的生產者將訊息發不到一個Exchange。Exchange會繫結到一個或者多個佇列上,他負責將訊息路由到佇列上。
Exchange不是簡單的訊息傳遞到佇列中,並不僅僅是一種穿透機制。AMQP定義了四種不同型別的Exchange,每一種都有不同的路由演算法。
四種標準的AMQP Exchange如下所示:

  • Direct:如果訊息routing key 與 binding的routing key直接匹配,訊息將會路由到該佇列上;
  • Topic:如果訊息的routing key 與binding的routing key 符合萬用字元匹配的話,將會把訊息路由到佇列上;
  • Headers:如果訊息引數列表中的頭訊息和值都與binding引數表中相匹配,訊息將會路由到佇列上,
  • Feanout:不管訊息的routing key 和引數的頭資訊是什麼,訊息將會路由到所有佇列上。
    藉助於這四種類型的Exchange,很容易就能定義任意數量的路由模式。而不是僅僅侷限於點對點和釋出—訂閱的模式。

    2. 配置Spring支援AMQP訊息


    RabbitMQ是一個流行的開源訊息代理,它實現了AMQP。Spring AMQP為 RabbitMQ提供了支援,包括 RabbitMQ連結工廠,模板以及Spring配置名稱空間。

配置RabbitMQ連線工廠—通過Spring名稱空間方式
配置連線工廠

<connection-factory id="connectionFactroy"/>

預設情況下連結工廠有一個預設的localhost的5672埠,使用者名稱和密碼均為 guest。在開發環境中這樣配置沒有問題但對於生產環境我們需要修改這些預設值。

<connection-factory id="connectionFactroy"
host="${rabbitmq.host}" port="${rabbitmq.port}" username="${rabbitmq.username}" password="${rabbitmq.password}" />

3.宣告佇列,Exchange以及binding

//宣告一個簡單的佇列
<admin connection-factroy="connectionFactroy"/>
<queue id="aplittle" name="spittle.alert"/>
//宣告一個複雜的佇列
<admin connection-factroy="connectionFactroy"/>
<queue name="spittle.alert.queue.1">
<queue name="spittle.alert.queue.2">
<queue name="spittle.alert.queue.3">
<fanout-exchange name="splittle.fanout">
<bindings>
    <binding queue="spittle.alert.queue.1"/>
    <binding queue="spittle.alert.queue.2"/>
    <binding queue="spittle.alert.queue.3"/>
    </bindings>
</fanout-exchange>

4. 使用RabbitTemplate傳送訊息

//配置RabbitTemplate名稱空間
<template id="rabbitTemplate" connection-factroy="connectionFactroy"/>
//使用使用RabbitTemplate傳送訊息
public class AlertServiceImpl implements AlertService{

    private RabbitTemplate rabbit;
    @Autowired
    public AlertServiceImpl(RabbitTemplate rabbit){
    this.rabbit=rabbit;
    }
    public void sendSpittleAlert(Spittle spittle){
        //1Exchange的名稱,2routing key,3要傳送的物件
        rabbit.convertAndSend("xxx","xxx","xxx");
    }
}

5. 使用RabbitTemplate接收訊息

共有兩種方式接收訊息,分別為使用RabbitTemplate同步的從佇列中獲取訊息。還有使用定義訊息驅動的AMQP POJO獲取訊息。

//RabbitTemplate同步獲取訊息
<templeate id="rabbitTemplate"
            connection-factory="connectionFactory"
            exchange="spittle.alert.exchange"
            routing-key="spittle-alerts"
            queue="spittle.alert.queue" />
Message msg = rabbit.receive();
//定義訊息驅動的AMQP POJO獲取訊息
public class SpittleAlertHandler{

    public void handleSpittleAlert(Spittle spittle){
        //....implementation goes here....
    }
}
//配置spring上下文監聽
<bean id="spittleListener"
        class="com.xxx.xxx.xxx.SpittleAlertHandler"/>
//宣告一個監聽容器和監聽器,當訊息到達時呼叫SpittleAlertHandler
<listener-container connection-factory="connectionFactory">
    <listener ref="spittleListener"
                method="handleSpittleAlert"
                queue-names="spittle.alert.queue">
    </listener>
</listener-container>