更新時(shí)間:2021-07-28 17:02:21 來(lái)源:動(dòng)力節(jié)點(diǎn) 瀏覽1560次
持久化消息和非持久化消息的發(fā)送策略
消息同步發(fā)送和異步發(fā)送
ActiveMQ支持同步、異步兩種發(fā)送模式將消息發(fā)送到broker上。同步發(fā)送過(guò)程中,發(fā)送者發(fā)送一條消息會(huì)阻塞直到broker反饋一個(gè)確認(rèn)消息,表示消息已經(jīng)被broker處理。這個(gè)機(jī)制提供了消息的安全性保障,但是由于是阻塞的操作,會(huì)影響到客戶端消息發(fā)送的性能。
異步發(fā)送的過(guò)程中,發(fā)送者不需要等待broker提供反饋,所以性能相對(duì)較高。但是可能會(huì)出現(xiàn)消息丟失的情況。所以使用異步發(fā)送的前提是在某些情況下允許出現(xiàn)數(shù)據(jù)丟失的情況。默認(rèn)情況下,非持久化消息是異步發(fā)送的,持久化消息并且是在非事務(wù)模式下是同步發(fā)送的。但是在開(kāi)啟事務(wù)的情況下,消息都是異步發(fā)送。由于異步發(fā)送的效率會(huì)比同步發(fā)送性能更高。所以在發(fā)送持久化消息的時(shí)候,盡量去開(kāi)啟事務(wù)會(huì)話。
除了持久化消息和非持久化消息的同步和異步特性外,還可以通過(guò)以下幾種方式來(lái)設(shè)置異步發(fā)送

消息的發(fā)送原理分析圖解

ProducerWindowSize的含義
producer每發(fā)送一個(gè)消息,統(tǒng)計(jì)一下發(fā)送的字節(jié)數(shù),當(dāng)字節(jié)數(shù)達(dá)到ProducerWindowSize值時(shí),需要等待broker的確認(rèn),才能繼續(xù)發(fā)送。代碼在:ActiveMQSession的1957行
主要用來(lái)約束在異步發(fā)送時(shí)producer端允許積壓的(尚未ACK)的消息的大小,且只對(duì)異步發(fā)送有意義。每次發(fā)送消息之后,都將會(huì)導(dǎo)致memoryUsage大小增加(+message.size),當(dāng)broker返回producerAck時(shí),memoryUsage尺寸減少(producerAck.size,此size表示先前發(fā)送消息的大小)。
Ø在brokerUrl中設(shè)置:"tcp://localhost:61616?jms.producerWindowSize=1048576",這種設(shè)置將會(huì)對(duì)所有的producer生效。
Ø在destinationUri中設(shè)置:"test-queue?producer.windowSize=1048576",此參數(shù)只會(huì)對(duì)使用此Destination實(shí)例的producer失效,將會(huì)覆蓋brokerUrl中的producerWindowSize值。
持久化消息和非持久化消息的存儲(chǔ)原理
正常情況下,非持久化消息是存儲(chǔ)在內(nèi)存中的,持久化消息是存儲(chǔ)在文件中的。能夠存儲(chǔ)的最大消息數(shù)據(jù)在${ActiveMQ_HOME}/conf/activemq.xml文件中的systemUsage節(jié)點(diǎn)
SystemUsage配置設(shè)置了一些系統(tǒng)內(nèi)存和硬盤(pán)容量

Ø從上面的配置我們需要get到一個(gè)結(jié)論,當(dāng)非持久化消息堆積到一定程度的時(shí)候,也就是內(nèi)存超過(guò)指定的設(shè)置閥值時(shí),ActiveMQ會(huì)將內(nèi)存中的非持久化消息寫(xiě)入到臨時(shí)文件,以便騰出內(nèi)存。但是它和持久化消息的區(qū)別是,重啟之后,持久化消息會(huì)從文件中恢復(fù),非持久化的臨時(shí)文件會(huì)直接刪除
ActiveMQ消息持久性對(duì)于可靠消息傳遞來(lái)說(shuō)是一種比較好的方法,即時(shí)發(fā)送者和接受者不是同時(shí)在線或者消息中心在發(fā)送者發(fā)送消息后宕機(jī)了,在消息中心重啟后仍然可以將消息發(fā)送出去。消息持久性的原理很簡(jiǎn)單,就是在發(fā)送消息出去后,消息中心首先將消息存儲(chǔ)在本地文件、內(nèi)存或者遠(yuǎn)程數(shù)據(jù)庫(kù),然后把消息發(fā)送給接受者,發(fā)送成功后再把消息從存儲(chǔ)中刪除,失敗則繼續(xù)嘗試。接下來(lái)我們來(lái)了解一下消息在broker上的持久化存儲(chǔ)實(shí)現(xiàn)方式
ActiveMQ支持多種不同的持久化方式,主要有以下幾種,不過(guò),無(wú)論使用哪種持久化方式,消息的存儲(chǔ)邏輯都是一致的。
ØKahaDB存儲(chǔ)(默認(rèn)存儲(chǔ)方式)ØJDBC存儲(chǔ)
ØMemory存儲(chǔ)
ØLevelDB存儲(chǔ)
ØJDBC With ActiveMQ Journal
KahaDB是目前默認(rèn)的存儲(chǔ)方式,可用于任何場(chǎng)景,提高了性能和恢復(fù)能力。消息存儲(chǔ)使用一個(gè)事務(wù)日志和僅僅用一個(gè)索引文件來(lái)存儲(chǔ)它所有的地址。KahaDB是一個(gè)專門(mén)針對(duì)消息持久化的解決方案,它對(duì)典型的消息使用模式進(jìn)行了優(yōu)化。在Kaha中,數(shù)據(jù)被追加到data logs中。當(dāng)不再需要log文件中的數(shù)據(jù)的時(shí)候,log文件會(huì)被丟棄。
KahaDB的配置方式

在data/kahadb這個(gè)目錄下,會(huì)生成四個(gè)文件
Ødb.data它是消息的索引文件,本質(zhì)上是B-Tree(B樹(shù)),使用B-Tree作為索引指向db-*.log里面存儲(chǔ)的消息
Ødb.redo用來(lái)進(jìn)行消息恢復(fù)
Ødb-*.log存儲(chǔ)消息內(nèi)容。新的數(shù)據(jù)以APPEND的方式追加到日志文件末尾。屬于順序?qū)懭?,因此消息存?chǔ)是比較快的。默認(rèn)是32M,達(dá)到閥值會(huì)自動(dòng)遞增
Ølock文件鎖,表示當(dāng)前獲得kahadb讀寫(xiě)權(quán)限的broker
JDBC存儲(chǔ)
使用JDBC持久化方式,數(shù)據(jù)庫(kù)會(huì)創(chuàng)建3個(gè)表:activemq_msgs,activemq_acks和activemq_lock。
ACTIVEMQ_MSGS消息表,queue和topic都存在這個(gè)表中
ACTIVEMQ_ACKS存儲(chǔ)持久訂閱的信息和最后一個(gè)持久訂閱接收的消息ID
ACTIVEMQ_LOCKS鎖表,用來(lái)確保某一時(shí)刻,只能有一個(gè)ActiveMQ broker實(shí)例來(lái)訪問(wèn)數(shù)據(jù)庫(kù)
JDBC存儲(chǔ)實(shí)踐

dataSource指定持久化數(shù)據(jù)庫(kù)的bean,createTablesOnStartup是否在啟動(dòng)的時(shí)候創(chuàng)建數(shù)據(jù)表,默認(rèn)值是true,這樣每次啟動(dòng)都會(huì)去創(chuàng)建數(shù)據(jù)表了,一般是第一次啟動(dòng)的時(shí)候設(shè)置為true,之后改成false
Mysql持久化Bean配置

添加Jar包依賴

消息消費(fèi)流程圖

消息重發(fā)的情況
在正常情況下,有幾中情況會(huì)導(dǎo)致消息重新發(fā)送
Ø在事務(wù)性會(huì)話中,沒(méi)有調(diào)用session.commit確認(rèn)消息或者調(diào)用
session.rollback方法回滾消息
Ø在非事務(wù)性會(huì)話中,ACK模式為CLIENT_ACKNOWLEDGE的情況下,沒(méi)有調(diào)用acknowledge或者調(diào)用了recover方法;
一個(gè)消息被redelivedred超過(guò)默認(rèn)的最大重發(fā)次數(shù)(默認(rèn)6次)時(shí),消費(fèi)端會(huì)給broker發(fā)送一個(gè)”poison ack”(ActiveMQMessageConsumer#dispatch:1460行),表示這個(gè)消息有毒,告訴broker不要再發(fā)了。這個(gè)時(shí)候broker會(huì)把這個(gè)消息放到DLQ(死信隊(duì)列)。
ActiveMQ采用消息推送方式,所以最適合的場(chǎng)景是默認(rèn)消息都可在短時(shí)間內(nèi)被消費(fèi)。數(shù)據(jù)量越大,查找和消費(fèi)消息就越慢,消息積壓程度與消息速度成反比。
1.吞吐量低。由于ActiveMQ需要建立索引,導(dǎo)致吞吐量下降。這是無(wú)法克服的缺點(diǎn),只要使用完全符合JMS規(guī)范的消息中間件,就要接受這個(gè)級(jí)別的TPS。
2.無(wú)分片功能。這是一個(gè)功能缺失,JMS并沒(méi)有規(guī)定消息中間件的集群、分片機(jī)制。而由于ActiveMQ是偉企業(yè)級(jí)開(kāi)發(fā)設(shè)計(jì)的消息中間件,初衷并不是為了處理海量消息和高并發(fā)請(qǐng)求。如果一臺(tái)服務(wù)器不能承受更多消息,則需要橫向拆分。ActiveMQ官方不提供分片機(jī)制,需要自己實(shí)現(xiàn)。
適用場(chǎng)景
對(duì)TPS要求比較低的系統(tǒng),可以使用ActiveMQ來(lái)實(shí)現(xiàn),一方面比較簡(jiǎn)單,能夠快速上手開(kāi)發(fā),另一方面可控性也比較好,還有比較好的監(jiān)控機(jī)制和界面
消息量巨大的場(chǎng)景。ActiveMQ不支持消息自動(dòng)分片機(jī)制,如果消息量巨大,導(dǎo)致一臺(tái)服務(wù)器不能處理全部消息,就需要自己開(kāi)發(fā)消息分片功能。
以上就是動(dòng)力節(jié)點(diǎn)小編介紹的"ActiveMQ原理分析",希望對(duì)大家有幫助,想了解更多可查看ActiveMQ教程。動(dòng)力節(jié)點(diǎn)在線學(xué)習(xí)教程,針對(duì)沒(méi)有任何Java基礎(chǔ)的讀者學(xué)習(xí),讓你從入門(mén)到精通,主要介紹了一些Java基礎(chǔ)的核心知識(shí),讓同學(xué)們更好更方便的學(xué)習(xí)和了解Java編程,感興趣的同學(xué)可以關(guān)注一下。
相關(guān)閱讀
Java實(shí)驗(yàn)班
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
Java就業(yè)班
有基礎(chǔ) 直達(dá)就業(yè)
Java夜校直播班
業(yè)余時(shí)間 高薪轉(zhuǎn)行
Java在職加薪班
工作1~3年,加薪神器
Java架構(gòu)師班
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問(wèn)老師會(huì)電話與您溝通安排學(xué)習(xí)