1. 程式人生 > >學習淘淘商城第五十四課(為何引入ActiveMQ)

學習淘淘商城第五十四課(為何引入ActiveMQ)

        我們在學習Solr索引的時候,每當新增一個商品後,都要把資料庫中的資料全部重新匯入到索引庫,特別消耗效能和時間,這顯然是我們所不能忍受的,這就需要優化我們的方案。最好是在商品新增的時候就單獨將該商品同步到索引庫,這樣便簡單快捷地實現了資料庫與索引庫的同步。

        擺在我們面前的方案有三個:

方案一:在taotao-manager中,新增商品的業務邏輯中,新增一段同步索引庫的業務邏輯。

缺點:很明顯,這樣會導致業務邏輯耦合度很高,業務拆分不明確,這與我們當初拆分工程,職能單一、明確的原則相違背,故不可採用。

方案二:業務邏輯在taotao-search中實現,呼叫服務在taotao-manager實現,業務邏輯分開。

缺點:服務與服務之間耦合度變高,服務的啟動有先後順序。服務設計的原則便是各自幹各自的活兒,啟動要保證互不依賴,服務之間不應該有呼叫行為,一旦有呼叫行為,依賴的一方便會因被依賴一方出現故障而無法工作。

方案三:使用訊息佇列,MQ是一個訊息中介軟體。如下圖所示。

       怎麼理解訊息中介軟體呢?我們可以把它理解為一個祕書,訊息的釋出者就是大老闆,大老闆下午三點要開個會,他只需跟祕書說一聲,下午三點,我要開個會,就行了,老闆不用管祕書是怎樣通知各專案經理的,也不用管專案經理要帶什麼材料,他所做的只是告訴祕書一聲而已。祕書負責與各個專案經理聯絡,告訴各個專案經理應該準備什麼。MQ便相當於"祕書"這個角色。當新增一個商品時,商品服務只需要告訴訊息中介軟體MQ,MQ便去通知其它服務做各自該做的事情,比如通知搜尋服務去同步索引庫,通知redis服務去同步快取,通知生成靜態頁面等等。


         常見的作為MQ的中介軟體有:ActiveMQ、RabbitMQ、Kafka。我們要學習的是ActiveMQ,其它的都大同小異。

         那麼,什麼是ActiveMQ?

         ActiveMQ 是Apache出品,最流行的,能力強勁的開源訊息匯流排。ActiveMQ 是一個完全支援JMS1.1和J2EE 1.4規範的 JMS Provider實現,儘管JMS規範出臺已經是很久的事情了,但是JMS在當今的J2EE應用中間仍然扮演著特殊的地位。
        主要特點:
1. 多種語言和協議編寫客戶端。語言: Java, C, C++, C#, Ruby, Perl, Python, PHP。應用協議: OpenWire,Stomp REST,WS Notification,XMPP,AMQP
2. 完全支援JMS1.1和J2EE 1.4規範 (持久化,XA訊息,事務)
3. 對Spring的支援,ActiveMQ可以很容易內嵌到使用Spring的系統裡面去,而且也支援Spring2.0的特性
4. 通過了常見J2EE伺服器(如 Geronimo,JBoss 4, GlassFish,WebLogic)的測試,其中通過JCA 1.5 resource adaptors的配置,可以讓ActiveMQ可以自動的部署到任何相容J2EE 1.4 商業伺服器上
5. 支援多種傳送協議:in-VM,TCP,SSL,NIO,UDP,JGroups,JXTA
6. 支援通過JDBC和journal提供高速的訊息持久化
7. 從設計上保證了高效能的叢集,客戶端-伺服器,點對點
8. 支援Ajax
9. 支援與Axis的整合
10. 可以很容易得呼叫內嵌JMS provider,進行測試

        ActiveMQ的訊息形式

        對於訊息的傳遞有兩種型別:
一種是點對點的,即一個生產者和一個消費者一一對應;
另一種是釋出/訂閱模式,即一個生產者產生訊息並進行傳送後,可以由多個消費者進行接收。
JMS定義了五種不同的訊息正文格式,以及呼叫的訊息型別,允許你傳送並接收以一些不同形式的資料,提供現有訊息格式的一些級別的相容性。我們用的最多的也就是TextMessage而已。
  · StreamMessage -- Java原始值的資料流
  · MapMessage--一套名稱-值對
  · TextMessage--一個字串物件
  · ObjectMessage--一個序列化的 Java物件
  · BytesMessage--一個位元組的資料流

        我們可以通過下面一張圖來加深理解,圖上半部分是"釋出/訂閱者"模式,兩個釋出者各自發布了一條訊息,每條訊息都可以被多個Consumer接收到。圖下半部分是"面對面"模式,兩個釋出者各自發布了一條訊息,壓入隊列當中,佇列的特點是先進先出,一旦有某個消費者拿走了一條訊息,佇列中就少了一條訊息,剩下的消費者就不可能再消費那條訊息了,因此也就做到了一對一。