ActiveMQ知識點(複習用,待整理)

作用;

1、異步:異步化提升整體系統的吞吐能力
2、解耦:新模塊接入時,可以做到最小代碼的改動;
3、削峯:設置流量緩衝池,讓後端系統按照自身吞吐能力消費,不被沖垮

Queue兩種消費方式:

1、同步阻塞方式(receive()):接收者調用MessageConsumer的receive()方式接收消息,receive在接收到消息之前將一直阻塞
2、異步非阻塞方式(onMessage):接受者調用MessageConsumer的setMessageListenerz註冊一個消息監聽器, 當消息到達後,系統自動調用監聽器MessageLister的onMessage()方法

1、先生產1條消息,只啓動1號消費者,
問題:1號消費者能消費消息嗎?
yes。
2、先生產1條消息,先啓動1號消費者再啓動2號消費者,
問題:2號消費者能消費消息嗎?
1號消費者可以消費,2號消費者不能。
3、先啓動2個消費者,再生產6條消息,
問題:請問消費情況如何?
一人一半。

Topic(發佈訂閱):

1、生產者將消息發送到topic中,每個消息可以有多個消費者
2、生產者和消費者之間有時間上的相關性,訂閱某一個topic的消費者只能消費訂閱後發佈的消息;
3、生產者生產時,topic不保存消息,假如無消費者就去生產,那就是一條廢消息,一般先啓動消費者再啓動生產者;

queue模式隊列和topic模式隊列
1、工作模式:
queue是負載均衡模式,如果當前沒有消費者,消息也不會丟失,如果有多個消費者,一條消息也只會發送給其中一個消費者;
topic是訂閱發佈模式,如果當前沒有消費者,消息會丟失,如果有多個訂閱者,訂閱者都會接收到消息 ;
2、有無狀態:
queue數據默認在MQ服務器上默認是文件形式保存,也可配置成DB存儲;
topic是無狀態的;
3、傳遞的完整性:
queue消息不會丟棄;
topic如果沒有消費者,消息會被丟棄 ;
4、獲取消息的方式:
queue是pull模式,消費者先發送個請求給broker是否有消息,有消息拉取消息;
topic是push,不需要消費者詢問,broker會主動把消息發送給訂閱者;

拉模式與推模式

a.點對點消息,如果沒有消費者在監聽隊列,消息將保留在隊列中,直至消息消費者連接到隊列爲止
這種消息傳遞模型是傳統意義上的懶模型或輪詢模型
在此模型中,消息不是自動推動給消息消費者的,而是要由消息消費者從隊列中請求獲得(拉模式)

b.pub/sub消息傳遞模型是一個推模型。在該模型中,消息會自動廣播,消息消費者無須通過主動請求或輪詢主題的方法來獲得新的消息

ActiveMQ消息類型

1、TextMessage 文本消息:攜帶一個java.lang.String作爲有效數據(負載)的消息,可用於字符串類型的信息交換
2、ObjectMessage 對象消息:攜帶一個可以序列化的Java對象作爲有效負載的消息,可用於Java對象類型的信息交換
3、MapMessage 映射消息:攜帶一組鍵值對的數據作爲有效負載的消息,有效數據值必須是Java原始數據類型(或者它們的包裝類)及String
即:byte , short , int , long , float , double , char , boolean , String
4、BytesMessage 字節消息 :攜帶一組原始數據類型的字節流作爲有效負載的消息
5、StreamMessage 流消息:攜帶一個原始數據類型流作爲有效負載的消息,它保持了寫入流時的數據類型,寫入什麼類型,則讀取也需要是相同的類型

持久化:

queue持久化:messageProdecer.setDeliveryMode(DeliveryMode.Persistent),默認是持久化。

本地事務:transaction事務偏生產者,acknowledge簽收偏消費者
false: 只要執行send,消息就進入到隊列中。關閉事務,那第二個參數acknowledge的設置需要有效。
true: 先執行send再執行commit,消息才被真正的提交到隊列中。消息需要批量發送,需要緩衝區處理。
事務性消息不管設置何種消息確認模式,都會自動被確認。

注意:生產者 —> broker 和 broker —> 消費者 完全是兩個操作,
他們的的事務、acknowledge一點關係也沒有,因爲他們的生產者和消費者的session一點關係也沒有啊!

生產者的事務是保證批量發送給broker,要麼一起成功要麼一起失敗。
消費者的事務保證brokee發送的消息到達消費者。。

事務消息重發機制:

重新傳遞消息的情況:
1、consumer使用了事務,且在session中調用了rollback();
2、consumer使用了事務,且在調用commit之前關閉;
3、consumer在client_acknowledge模式下,在session中調用了recover();
4、消費者消費消息的時候down了,消息自動轉入其他消費者。
默認重發次數爲6,重發的時間間隔爲1秒;

acknowledge消息確認機制:

消息的成功消費分爲三個階段:
1、consumer從broker接收消息;2、consumer處理消息;3、consumer向broker確認消息已經消費。
有三種策略:
1、默認的自動簽收(Session.auto_acknowledge):consumer成功從messageListener.onMessage方法返回,session自動確認消息,broker刪除消息。
2、手動簽收(Session.client_acknowledge):consumer需要手動調用message.acknowledge()方法確認消息,broker纔會刪除消息。
3、允許重複消息(Session.dups_ok_acknowledge):不是必須確認,消息可能重複發送。

傳輸協議:

默認使用的是TCP協議,tcp的默認端口是61616。
推薦使用NIO協議,是基於Tcp協議進行了擴展和優化,具有更好的擴展性。
配置修改:conf目錄下的activemq.xml文件的transportConnetors節點下的transportConnector節點name屬性改成auto+nio,uri屬性改成auto+nio。

可持久化:

1、默認的是kahaDB:基於日誌文件。配置在persistenceAdapter節點配置日誌文件目錄。(默認是${activemq}/data/kahadb/)
2、jdbc:基於第三方數據庫,比如mysql,在persistenceAdapter節點,改成jdbc的配置,並配置DataSource。
3、levelDB

kahadb存儲使用的是事務日誌加索引文件來存儲它的所有地址。
db-1.log、db.data、db.free、db.redo、lock
db-num.log: 儲存數據到預定義的文件大小中,默認每個文件32M,當數據文件滿時一個新的文件會隨之創建。當文件中不再有索引引用的數據,文件會被刪除。
db.data: 消息的索引文件,使用BTree作爲索引指向db-num.log裏面存儲的消息。
db.redo:用來進行消息恢復的,如果kahaDb消息儲存在強制退出後啓動,用於恢復BTree索引。
lock: lock文件表示鎖,表示獲得當前kahadb讀寫權限的broker。

jdbc存儲模式:

有三張表:
1、activemq_msgs: 用於存儲消息的表;
2、activemq_acks: 存儲訂閱關係;
3、activemq_lock: 集羣環境中使用,同一時間只能有一個master broker;

如果是queue的話,在沒有消費者的情況下會將消息存儲在activemq_msgs表中,只要有任何一個消費者消費過了,消費之後這些消息將被清除。
如果是topic的話,普通訂閱不會持久化消息,持久化訂閱需要先啓動生產者再生產消息,之後無論訂閱者是否在線,最終都會接收到消息。
不在的話,等到再次連接的時候會將沒有收到的消息全部接收處理。

開發注意:

  1. 數據庫jar包放到activemq lib目錄下;
  2. createTableOnStartup屬性啓動完成後去掉,或者改爲false;
  3. 數據庫編碼使用latin格式;

可以使用jdbc with journal模式,使用了高速緩存寫入技術,大大提高了性能,先寫入journal文件再寫入數據庫。

高可用:

引入消息隊列之後該如何保證其高可用?
使用zookeeper + replicated-leveldb-store的主從集羣。是基於zookeeper和levelDB搭建的activeMQ集羣。
集羣提供主備方式的高可用集羣功能,避免單點故障。
原理:使用zookeeper集羣註冊所有的activeMq,但只有其中的一個broker可以提供服務被視爲master,
其他broker處於待機狀態,被視爲slave。如果master不能提供服務,zookeeper會從slave選舉一個充當master,
slave連接master並同步它的存儲狀態,slave不接受客戶端的請求。

異步投遞:

對於慢的consumer,使用同步發送消息可能造成producer阻塞情況,慢消費者適合異步投遞。
activeMQ默認使用的是異步發送的模式,除非明確指定同步發送或在沒有使用事務的情況下發送持久化消息,這兩個情況是同步的。
使用場景:允許在失敗的情況下有少量的數據丟失、發送消息量在比較密集的情況下。
配置:
1、connection uri
2、connectionFactory
3、connection

異步消息如何確定發送成功?
異步發送方式是需要接收回調的。

同步發送和異步發送的區別。
同步發送等send不阻塞了就表示一定發送成功,
異步發送需要接收回調並又client再判斷一次是否發送成功。

延時投遞:

需要在activemq conf 目錄下的activemq.xml文件的broker節點配置 schedulersupport = true;
有四大參數:
amq_scheduler_delay: 延遲投遞的時間;
amq_scheduler_period: 重複投遞的時間間隔;
amq_scheduler_repeat;重複投遞的次數;
amq_scheduler_cron: cron表達式;

死信隊列:

有毒消息poison ack:
一個消息超過最大的重發次數(默認爲6次)時,消費端會給broker發送“poison ack”,表示這個消息有毒,告訴broker不要再發了
這個時候broker會把這個消息放到死信隊列(dead letter queue)
將所有的deadletter保存在一個共享隊列中,共享隊列默認爲ActiveMQ.DLQ

如何保證消息不被重複消費?

準備一個第三方服務來做消費記錄,以redis爲例,給消息分配一個全局id,只要消費過該消息,將<id,message>以k-v鍵值對形式存入redis, 那消費者在開始消費之前,先去redis查詢有沒有消費記錄即可

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章