1. 程式人生 > >【Spring】使用Spring和AMQP發送接收消息(上)

【Spring】使用Spring和AMQP發送接收消息(上)

com load 設定 支持 消息發送 結果 alt 來看 接下來

講AMQP之前,先講下傳統的JMS的消息模型,JMS中主要有三個參與者:消息的生產者、消費者、傳遞消息的通道(隊列或者主題),兩種消息模型如下:
通道是隊列:

通道是隊列:

技術分享

通道是主題:

技術分享

在JMS中,雖然通道有助於解耦消息的生產者和消費者,但這兩者依然會與通道相耦合。生產者會將消息發布到一個特定的隊列或主題上,消費者從特定的隊列或主題上接收這些消息,通道具有雙重責任,就是傳遞數據和確定這些消息該發送到什麽地方,隊列的話會使用點對點算法發送,主題的話就使用發布-訂閱方式。
而使用AMQP的話,生產者並不會直接將消息發布到隊列中,AMQP的消息的生產者以及傳遞消息的隊列之間引入間接機制Exchange,Exchange再與隊列綁定。關系圖如下:

技術分享

從圖可以看出Exchange收到消息後,Exchange會將信息路由到隊列上,消費者再從隊列中取數據並處理。這裏Exchange不是簡單地把消息傳遞到隊列中,AMQP定義了四種不同類型的Exchange,每種都有不同的路由算法,以此決定是否將信息放到隊列中。根據Exchange算法的不同,它可能會使用消息的routing key和/或參數,並將其與Exchange和隊列之間的binding和routing key和參數進行對比,如果對比結果滿足相應的算法,那麽消息就路由到該隊列上。

AMQP中定義的四種不同類型的Exchange:

Direct:如果消息的routing key與binding的routing key直接匹配的話,消息將會路由到該隊列上;
Topic:如果消息的routing key與binding的routing key符合通配符匹配的話,消息將會路由到該隊列上;
Headers:如果消息參數表中的頭信息和值都與binding參數表相匹配,消息將會路由到該隊列上;
Fanout:不管消息的routing key和參數表的頭信息/值是什麽,消息將會路由到所有隊列上。
這裏要深入了解AMQP的到www.amqp.org查看,下面使用Spring、AMQP實現發送、接收消息。

先配置Spring支持AMQP消息

使用Spring AMQP前要先配置一個連接工廠,具體來講,這裏選擇配置RabbitMQ連接工廠。RabbitMQ實現了AMQP,也是目前較常用的消息代理。使用RabbitMQ發送接收消息前,要先安裝RabbitMQ,具體安裝步驟可以在www.rabbitmq.com/download.html上找到安裝指南,這裏就不詳細展開。

配置RabbitMQ連接工廠最簡單的方式是使用Spring AMQP所提供的rabbit配置命名空間,要使用該功能,首先要確保Spring配置文件中聲明了該模式:

技術分享
<?xml version="1.0" encoding="UTF-8"?>  
<beans:beans xmlns="http://www.springframework.org/schema/beans"  
    xmlns:rabbit="http://www.springframework.org/schema/rabbit"  
    xsi:schemaLocation="http://www.springframework.org/schema/beans  
    http://www.springframework.org/schema/beans/spring-beans.xsd  
    http://www.springframework.org/schema/rabbit  
    http://www.springframework.org/schema/rabbit/spring-rabbit-1.0.xsd"> 
...
</beans:beans>
技術分享

這個配置不是必須的,這裏選擇將rabbit作為首選命名空間,將beans作為第二的命名空間,因為在這個配置中,會更多的聲明rabbit而不是bean,這樣的話,只會有少量的bean元素使用“beans:”前綴,而rabbit元素就能避免使用前綴了。

rabbit命名空間包含了多個在Spring中配置RabbitMQ的元素,用得最多的就是<connection-factory>,使用時最好給其設置一個bean ID,不然就難將連接工廠裝配到需要它的bean中了。

<connectioin-factory id="connectionFactory">

連接工廠默認情況下會設置RabbitMQ服務器監聽localhost的5672端口,用戶名密碼都為guest,一般在開發環境可以不作修改,在生產環境的修改方式如下 :

技術分享
<connectioin-factory id="connectionFactory" 
      host="${rabbitmq.host}"
      post="${rabbitmq.post}"
      username="${rabbitmq.username}"
      password="${rabbitmq.password}" 
/>
技術分享

這樣設置的好處是具體值可以到屬性文件中配置。

接下來看看如何創建隊列、Exchange、binding

在傳統的JMS中,隊列和主題的路由行為是通過規範建立的,而AMQP依賴於如何定義隊列和Exchange以及如何將它們綁定在一起。聲明隊列、Exchange和binding的一種方式是使用RabbitMQ Channel接口的各種方法,不過這裏使用rabbit命名空間更加方便,它包含了多個元素,可以幫我們聲明隊列、Exchange以及將它們結合在一起的binding。元素如下:

技術分享

這些配置元素要與<admin>元素一起使用,<admin>元素會創建一個RabbitMQ管理組件,如果上述表格中的元素在RabbitMQ代理中尚未存在的話,<admin>會自動創建它們。
比如現在想聲明名為spittle.test.queue的隊列,只需要在Spring配置中添加如下配置即可:

<admin connection-factory="connectionFactory" />
<queue id="spittleTestQueue" name="spittle.test" />

當如此配置時,Exchange默認是一個沒有名稱的direct Exchange,所有隊列都會綁定到這個Exchange中,並且routing key與隊列的名稱相同。在這樣的配置下,我們可以將消息發送到這個沒有名稱的Exchange上,並將routing key設定為spittle.test.queue,這樣消息就會路由到這個隊列中(其實這裏就類似於JMS的點對點模型)。
其他有意思的路由需要我們自行聲明一個或更多的Exchange,並將其綁定到隊列上,比如不管routing key是什麽, 要將消息路由到多個隊列上,可以按照如下方式配置一個fanout以及多個隊列:

技術分享
<admin connection-factory="connectionFactory" />
<queue  name="spittle.test.queue.1" >
<queue  name="spittle.test.queue.2" >
<queue  name="spittle.test.queue.3" >
<fanout-exchange name="spittle.fanout">
  <bindings>
    <binding queue="spittle.test.queue.1" />
    <binding queue="spittle.test.queue.2" />
    <binding queue="spittle.test.queue.3" />
  </bindings>
</fanout-exchange>
技術分享

其他類型的Exchange讀者可以根據上面的表格自行嘗試,下一篇將繼續寫如何發送消息。

【Spring】使用Spring和AMQP發送接收消息(上)