ActiveMQ 面試題

ActiveMQ是什么?

消息中間件。可以在分布式系統的不同服務之間進行消息的發送接收

Activemq的作用以及原理

Activemq 的作用就是系統之間進行通信。 當然可以使用其他方式進行系統間通信, 如果使用 Activemq 的話可以對系統之間的調用進行解耦, 實現系統間的異步通信。 原理就是生產者生產消息, 把消息發送給activemq。 Activemq 接收到消息, 然后查看有多少個消費者, 然后把消息轉發給消費者, 此過程中生產者無需參與。 消費者接收到消息后做相應的處理和生產者沒有任何關系。

  • 兩種消息模式:
    p2p(point-to-point) (點對點)
    一對一消息(私聊),Queue消息,同時一個收。
    publish(發布)-subscribe(訂閱) (發布-訂閱方式)
    一對多消息(群發),Topic消息,同時可以多個收。

  • 實際項目應用場景?
    刪除商品-》發送消息-》接收消息-》刪除索引。
    商品狀態更新-》發送消息-》接收消息-》導入索引庫。

消息丟了怎么辦?

這得從java的java.net.SocketException異常說起。簡單點說就是當網絡發送方發送一堆數據,然后調用close關閉連接之后。這些發送的數據都在接收者的緩存里,接收者如果調用read方法仍舊能從緩存中讀取這些數據,盡管對方已經關閉了連接。但是當接收者嘗試發送數據時,由于此時連接已關閉,所以會發生異常,這個很好理解。不過需要注意的是,當發生SocketException后,原本緩存區中數據也作廢了,此時接收者再次調用read方法去讀取緩存中的數據,就會報Software caused connection abort: recv failed錯誤。
通過抓包得知,ActiveMQ會每隔10秒發送一個心跳包,這個心跳包是服務器發送給客戶端的,用來判斷客戶端死沒死。如果你看過上面第一條,就會知道非持久化消息堆積到一定程度會寫到文件里,這個寫的過程會阻塞所有動作,而且會持續20到30秒,并且隨著內存的增大而增大。當客戶端發完消息調用connection.close()時,會期待服務器對于關閉連接的回答,如果超過15秒沒回答就直接調用socket層的close關閉tcp連接了。這時客戶端發出的消息其實還在服務器的緩存里等待處理,不過由于服務器心跳包的設置,導致發生了java.net.SocketException異常,把緩存里的數據作廢了,沒處理的消息全部丟失。
解決方案:用持久化消息,或者非持久化消息及時處理不要堆積,或者啟動事務,啟動事務后,commit()方法會負責任的等待服務器的返回,也就不會關閉連接導致消息丟失了。

如何解決消息重復問題?

一般來說我們可以在業務段加一張表,用來存放消息是否執行成功,每次業務事物commit之后,告知服務端,已經處理過該消息,這樣即使你消息重發了,也不會導致重復處理。

  • 大致流程如下:
    業務端的表記錄已經處理消息的id,每次一個消息進來之前先判斷該消息是否執行過,如果執行過就放棄,如果沒有執行就開始執行消息,消息執行完成之后存入這個消息的id.

持久化消息非常慢

默認的情況下,非持久化的消息是異步發送的,持久化的消息是同步發送的,遇到慢一點的硬盤,發送消息的速度是無法忍受的。但是在開啟事務的情況下,消息都是異步發送的,效率會有2個數量級的提升。所以在發送持久化消息時,請務必開啟事務模式。其實發送非持久化消息時也建議開啟事務,因為根本不會影響性能。

消息的不均勻消費

有時在發送一些消息之后,開啟2個消費者去處理消息。會發現一個消費者處理了所有的消息,另一個消費者根本沒收到消息。原因在于ActiveMQ的prefetch機制。當消費者去獲取消息時,不會一條一條去獲取,而是一次性獲取一批,默認是1000條。這些預獲取的消息,在還沒確認消費之前,在管理控制臺還是可以看見這些消息的,但是不會再分配給其他消費者,此時這些消息的狀態應該算作“已分配未消費”,如果消息最后被消費,則會在服務器端被刪除,如果消費者崩潰,則這些消息會被重新分配給新的消費者。但是如果消費者既不消費確認,又不崩潰,那這些消息就永遠躺在消費者的緩存區里無法處理。更通常的情況是,消費這些消息非常耗時,你開了10個消費者去處理,結果發現只有一臺機器吭哧吭哧處理,另外9臺啥事不干。
解決方案:將prefetch設為1,每次處理1條消息,處理完再去取,這樣也慢不了多少。

死信隊列

如果你想在消息處理失敗后,不被服務器刪除,還能被其他消費者處理或重試,可以關閉AUTO_ACKNOWLEDGE,將ack交由程序自己處理。那如果使用了AUTO_ACKNOWLEDGE,消息是什么時候被確認的,還有沒有阻止消息確認的方法?有!
消費消息有2種方法,一種是調用consumer.receive()方法,該方法將阻塞直到獲得并返回一條消息。這種情況下,消息返回給方法調用者之后就自動被確認了。另一種方法是采用listener回調函數,在有消息到達時,會調用listener接口的onMessage方法。在這種情況下,在onMessage方法執行完畢后,消息才會被確認,此時只要在方法中拋出異常,該消息就不會被確認。那么問題來了,如果一條消息不能被處理,會被退回服務器重新分配,如果只有一個消費者,該消息又會重新被獲取,重新拋異常。就算有多個消費者,往往在一個服務器上不能處理的消息,在另外的服務器上依然不能被處理。難道就這么退回--獲取--報錯死循環了嗎?
在重試6次后,ActiveMQ認為這條消息是“有毒”的,將會把消息丟到死信隊列里。如果你的消息不見了,去ActiveMQ.DLQ里找找,說不定就躺在那里。

ActiveMQ中的消息重發時間間隔和重發次數嗎?

ActiveMQ:是Apache出品,最流行的,能力強勁的開源消息總線。是一個完全支持JMS1.1和J2EE 1.4規范的 JMS Provider實現。JMS(Java消息服務):是一個Java平臺中關于面向消息中間件(MOM)的API,用于在兩個應用程序之間,或分布式系統中發送消息,進行異步通信。
首先,我們得大概了解下,在哪些情況下,ActiveMQ服務器會將消息重發給消費者,這里為簡單起見,假定采用的消息發送模式為隊列(即消息發送者和消息接收者)。
① 如果消息接收者在處理完一條消息的處理過程后沒有對MOM進行應答,則該消息將由MOM重發.
② 如果我們隊某個隊列設置了預讀參數(consumer.prefetchSize),如果消息接收者在處理第一條消息時(沒向MOM發送消息接收確認)就宕機了,則預讀數量的所有消息都將被重發!
③ 如果Session是事務的,則只要消息接收者有一條消息沒有確認,或發送消息期間MOM或客戶端某一方突然宕機了,則該事務范圍中的所有消息MOM都將重發。
④ 說到這里,大家可能會有疑問,ActiveMQ消息服務器怎么知道消費者客戶端到底是消息正在處理中還沒來得急對消息進行應答還是已經處理完成了沒有應答或是宕機了根本沒機會應答呢?其實在所有的客戶端機器上,內存中都運行著一套客戶端的ActiveMQ環境,該環境負責緩存發來的消息,負責維持著和ActiveMQ服務器的消息通訊,負責失效轉移(fail-over)等,所有的判斷和處理都是由這套客戶端環境來完成的。
我們可以來對ActiveMQ的重發策略(Redelivery Policy)來進行自定義配置,其中的配置參數主要有以下幾個:
可用的屬性:屬性 默認值 說明
l collisionAvoidanceFactor 默認值0.15 , 設置防止沖突范圍的正負百分比,只有啟用useCollisionAvoidance參數時才生效。
l maximumRedeliveries 默認值6 , 最大重傳次數,達到最大重連次數后拋出異常。為-1時不限制次數,為0時表示不進行重傳。
l maximumRedeliveryDelay 默認值-1, 最大傳送延遲,只在useExponentialBackOff為true時有效(V5.5),假設首次重連間隔為10ms,倍數為2,那么第二次重連時間間隔為 20ms,第三次重連時間間隔為40ms,當重連時間間隔大的最大重連時間間隔時,以后每次重連時間間隔都為最大重連時間間隔。
l initialRedeliveryDelay 默認值1000L, 初始重發延遲時間
l redeliveryDelay 默認值1000L, 重發延遲時間,當initialRedeliveryDelay=0時生效(v5.4)
l useCollisionAvoidance 默認值false, 啟用防止沖突功能,因為消息接收時是可以使用多線程并發處理的,應該是為了重發的安全性,避開所有并發線程都在同一個時間點進行消息接收處理。所有線程在同一個時間點處理時會發生什么問題呢?應該沒有問題,只是為了平衡broker處理性能,不會有時很忙,有時很空閑。
l useExponentialBackOff 默認值false, 啟用指數倍數遞增的方式增加延遲時間。
l backOffMultiplier 默認值5, 重連時間間隔遞增倍數,只有值大于1和啟用useExponentialBackOff參數時才生效。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,461評論 6 532
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,538評論 3 417
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,423評論 0 375
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,991評論 1 312
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,761評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,207評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,268評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,419評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,959評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,782評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,983評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,528評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,222評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,653評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,901評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,678評論 3 392
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,978評論 2 374

推薦閱讀更多精彩內容

  • 個人專題目錄[http://www.lxweimin.com/p/140e2a59db2c] 一、JMS簡介 全稱...
    Java及SpringBoot閱讀 2,100評論 0 10
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,785評論 18 139
  • 1、前言 之前我們通過兩篇文章(架構設計:系統間通信(19)——MQ:消息協議(上)、架構設計:系統間通信(20)...
    境里婆娑閱讀 1,896評論 0 4
  • 什么是activeMQ activeMQ是一種開源的,實現了JMS1.1規范的,面向消息(MOM)的中間件,為應用...
    趙鐵柱啊閱讀 1,921評論 1 6
  • 今日夏至,太陽運行至黃經90度(夏至點),太陽直射地面的位置到達一年的最北端,北半球各地的白晝時間達到全年最長。 ...
    緋云久閱讀 292評論 0 0