【Spring】使用Spring和AMQP發送接收消息(上)
講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發送接收消息(上)