更新時(shí)間:2023-01-28 16:28:15 來源:動(dòng)力節(jié)點(diǎn) 瀏覽1417次
在我們的日常生活中避免不開的需要接觸到試題,試題的目的就是應(yīng)對(duì)考試題目,小編知道有不少同學(xué)在找比較規(guī)范的面試題,以下是我收集整理的一些activemq筆試題,可供大家參考:
1. ActiveMQ服務(wù)器宕機(jī)怎么辦?
這得從ActiveMQ的儲(chǔ)存機(jī)制說起。在通常的情況下,非持久化消息是存儲(chǔ)在內(nèi)存中的,持久化消息是存儲(chǔ)在文件中的,它們的最大限制在配置文件的節(jié)點(diǎn)中配置。但是,在非持久化消息堆積到一定程度,內(nèi)存告急的時(shí)候,ActiveMQ會(huì)將內(nèi)存中的非持久化消息寫入臨時(shí)文件中,以騰出內(nèi)存。雖然都保存到了文件里,但它和持久化消息的區(qū)別是,重啟后持久化消息會(huì)從文件中恢復(fù),非持久化的臨時(shí)文件會(huì)直接刪除。
那如果文件增大到達(dá)了配置中的最大限制的時(shí)候會(huì)發(fā)生什么?我做了以下實(shí)驗(yàn):
設(shè)置2G左右的持久化文件限制,大量生產(chǎn)持久化消息直到文件達(dá)到最大限制,此時(shí)生產(chǎn)者阻塞,但消費(fèi)者可正常連接并消費(fèi)消息,等消息消費(fèi)掉一部分,文件刪除又騰出空間之后,生產(chǎn)者又可繼續(xù)發(fā)送消息,服務(wù)自動(dòng)恢復(fù)正常。
設(shè)置2G左右的臨時(shí)文件限制,大量生產(chǎn)非持久化消息并寫入臨時(shí)文件,在達(dá)到最大限制時(shí),生產(chǎn)者阻塞,消費(fèi)者可正常連接但不能消費(fèi)消息,或者原本慢速消費(fèi)的消費(fèi)者,消費(fèi)突然停止。整個(gè)系統(tǒng)可連接,但是無(wú)法提供服務(wù),就這樣掛了。
具體原因不詳,解決方案:盡量不要用非持久化消息,非要用的話,將臨時(shí)文件限制盡可能的調(diào)大。
2. 丟消息怎么辦?
這得從java的java.net.SocketException異常說起。簡(jiǎn)單點(diǎn)說就是當(dāng)網(wǎng)絡(luò)發(fā)送方發(fā)送一堆數(shù)據(jù),然后調(diào)用close關(guān)閉連接之后。這些發(fā)送的數(shù)據(jù)都在接收者的緩存里,接收者如果調(diào)用read方法仍舊能從緩存中讀取這些數(shù)據(jù),盡管對(duì)方已經(jīng)關(guān)閉了連接。但是當(dāng)接收者嘗試發(fā)送數(shù)據(jù)時(shí),由于此時(shí)連接已關(guān)閉,所以會(huì)發(fā)生異常,這個(gè)很好理解。不過需要注意的是,當(dāng)發(fā)生SocketException后,原本緩存區(qū)中數(shù)據(jù)也作廢了,此時(shí)接收者再次調(diào)用read方法去讀取緩存中的數(shù)據(jù),就會(huì)報(bào)Software caused connection abort: recv failed錯(cuò)誤。
通過抓包得知,ActiveMQ會(huì)每隔10秒發(fā)送一個(gè)心跳包,這個(gè)心跳包是服務(wù)器發(fā)送給客戶端的,用來判斷客戶端死沒死。如果你看過上面第一條,就會(huì)知道非持久化消息堆積到一定程度會(huì)寫到文件里,這個(gè)寫的過程會(huì)阻塞所有動(dòng)作,而且會(huì)持續(xù)20到30秒,并且隨著內(nèi)存的增大而增大。當(dāng)客戶端發(fā)完消息調(diào)用connection.close()時(shí),會(huì)期待服務(wù)器對(duì)于關(guān)閉連接的回答,如果超過15秒沒回答就直接調(diào)用socket層的close關(guān)閉tcp連接了。這時(shí)客戶端發(fā)出的消息其實(shí)還在服務(wù)器的緩存里等待處理,不過由于服務(wù)器心跳包的設(shè)置,導(dǎo)致發(fā)生了java.net.SocketException異常,把緩存里的數(shù)據(jù)作廢了,沒處理的消息全部丟失。
解決方案:用持久化消息,或者非持久化消息及時(shí)處理不要堆積,或者啟動(dòng)事務(wù),啟動(dòng)事務(wù)后,commit()方法會(huì)負(fù)責(zé)任的等待服務(wù)器的返回,也就不會(huì)關(guān)閉連接導(dǎo)致消息丟失了。
3. 持久化消息非常慢。
默認(rèn)的情況下,非持久化的消息是異步發(fā)送的,持久化的消息是同步發(fā)送的,遇到慢一點(diǎn)的硬盤,發(fā)送消息的速度是無(wú)法忍受的。但是在開啟事務(wù)的情況下,消息都是異步發(fā)送的,效率會(huì)有2個(gè)數(shù)量級(jí)的提升。所以在發(fā)送持久化消息時(shí),請(qǐng)務(wù)必開啟事務(wù)模式。其實(shí)發(fā)送非持久化消息時(shí)也建議開啟事務(wù),因?yàn)楦静粫?huì)影響性能。
4. 消息的不均勻消費(fèi)。
有時(shí)在發(fā)送一些消息之后,開啟2個(gè)消費(fèi)者去處理消息。會(huì)發(fā)現(xiàn)一個(gè)消費(fèi)者處理了所有的消息,另一個(gè)消費(fèi)者根本沒收到消息。原因在于ActiveMQ的prefetch機(jī)制。當(dāng)消費(fèi)者去獲取消息時(shí),不會(huì)一條一條去獲取,而是一次性獲取一批,默認(rèn)是1000條。這些預(yù)獲取的消息,在還沒確認(rèn)消費(fèi)之前,在管理控制臺(tái)還是可以看見這些消息的,但是不會(huì)再分配給其他消費(fèi)者,此時(shí)這些消息的狀態(tài)應(yīng)該算作“已分配未消費(fèi)”,如果消息最后被消費(fèi),則會(huì)在服務(wù)器端被刪除,如果消費(fèi)者崩潰,則這些消息會(huì)被重新分配給新的消費(fèi)者。但是如果消費(fèi)者既不消費(fèi)確認(rèn),又不崩潰,那這些消息就永遠(yuǎn)躺在消費(fèi)者的緩存區(qū)里無(wú)法處理。更通常的情況是,消費(fèi)這些消息非常耗時(shí),你開了10個(gè)消費(fèi)者去處理,結(jié)果發(fā)現(xiàn)只有一臺(tái)機(jī)器吭哧吭哧處理,另外9臺(tái)啥事不干。
解決方案:將prefetch設(shè)為1,每次處理1條消息,處理完再去取,這樣也慢不了多少。
5. 死信隊(duì)列。
如果你想在消息處理失敗后,不被服務(wù)器刪除,還能被其他消費(fèi)者處理或重試,可以關(guān)閉AUTO_ACKNOWLEDGE,將ack交由程序自己處理。那如果使用了AUTO_ACKNOWLEDGE,消息是什么時(shí)候被確認(rèn)的,還有沒有阻止消息確認(rèn)的方法?有!
消費(fèi)消息有2種方法,一種是調(diào)用consumer.receive()方法,該方法將阻塞直到獲得并返回一條消息。這種情況下,消息返回給方法調(diào)用者之后就自動(dòng)被確認(rèn)了。另一種方法是采用listener回調(diào)函數(shù),在有消息到達(dá)時(shí),會(huì)調(diào)用listener接口的onMessage方法。在這種情況下,在onMessage方法執(zhí)行完畢后,消息才會(huì)被確認(rèn),此時(shí)只要在方法中拋出異常,該消息就不會(huì)被確認(rèn)。那么問題來了,如果一條消息不能被處理,會(huì)被退回服務(wù)器重新分配,如果只有一個(gè)消費(fèi)者,該消息又會(huì)重新被獲取,重新拋異常。就算有多個(gè)消費(fèi)者,往往在一個(gè)服務(wù)器上不能處理的消息,在另外的服務(wù)器上依然不能被處理。難道就這么退回--獲取--報(bào)錯(cuò)死循環(huán)了嗎?
在重試6次后,ActiveMQ認(rèn)為這條消息是“有毒”的,將會(huì)把消息丟到死信隊(duì)列里。如果你的消息不見了,去ActiveMQ.DLQ里找找,說不定就躺在那里。
6. ActiveMQ中的消息重發(fā)時(shí)間間隔和重發(fā)次數(shù)嗎?
ActiveMQ:是Apache出品,最流行的,能力強(qiáng)勁的開源消息總線。是一個(gè)完全支持JMS1.1和J2EE 1.4規(guī)范的 JMS Provider實(shí)現(xiàn)。JMS(Java消息服務(wù)):是一個(gè)Java平臺(tái)中關(guān)于面向消息中間件(MOM)的API,用于在兩個(gè)應(yīng)用程序之間,或分布式系統(tǒng)中發(fā)送消息,進(jìn)行異步通信。
首先,我們得大概了解下,在哪些情況下,ActiveMQ服務(wù)器會(huì)將消息重發(fā)給消費(fèi)者,這里為簡(jiǎn)單起見,假定采用的消息發(fā)送模式為隊(duì)列(即消息發(fā)送者和消息接收者)。
① 如果消息接收者在處理完一條消息的處理過程后沒有對(duì)MOM進(jìn)行應(yīng)答,則該消息將由MOM重發(fā).
② 如果我們隊(duì)某個(gè)隊(duì)列設(shè)置了預(yù)讀參數(shù)(consumer.prefetchSize),如果消息接收者在處理第一條消息時(shí)(沒向MOM發(fā)送消息接收確認(rèn))就宕機(jī)了,則預(yù)讀數(shù)量的所有消息都將被重發(fā)!
③ 如果Session是事務(wù)的,則只要消息接收者有一條消息沒有確認(rèn),或發(fā)送消息期間MOM或客戶端某一方突然宕機(jī)了,則該事務(wù)范圍中的所有消息MOM都將重發(fā)。
④ 說到這里,大家可能會(huì)有疑問,ActiveMQ消息服務(wù)器怎么知道消費(fèi)者客戶端到底是消息正在處理中還沒來得急對(duì)消息進(jìn)行應(yīng)答還是已經(jīng)處理完成了沒有應(yīng)答或是宕機(jī)了根本沒機(jī)會(huì)應(yīng)答呢?其實(shí)在所有的客戶端機(jī)器上,內(nèi)存中都運(yùn)行著一套客戶端的ActiveMQ環(huán)境,該環(huán)境負(fù)責(zé)緩存發(fā)來的消息,負(fù)責(zé)維持著和ActiveMQ服務(wù)器的消息通訊,負(fù)責(zé)失效轉(zhuǎn)移(fail-over)等,所有的判斷和處理都是由這套客戶端環(huán)境來完成的。
我們可以來對(duì)ActiveMQ的重發(fā)策略(Redelivery Policy)來進(jìn)行自定義配置,其中的配置參數(shù)主要有以下幾個(gè):
可用的屬性
屬性 默認(rèn)值 說明
以上就是“工程師相關(guān)崗位的activemq筆試題”,你能回答上來嗎?如果想要了解更多的Java面試題相關(guān)內(nèi)容,可以關(guān)注動(dòng)力節(jié)點(diǎn)Java官網(wǎng)。
相關(guān)閱讀
0基礎(chǔ) 0學(xué)費(fèi) 15天面授
有基礎(chǔ) 直達(dá)就業(yè)
業(yè)余時(shí)間 高薪轉(zhuǎn)行
工作1~3年,加薪神器
工作3~5年,晉升架構(gòu)
提交申請(qǐng)后,顧問老師會(huì)電話與您溝通安排學(xué)習(xí)
初級(jí) 202925
初級(jí) 203221
初級(jí) 202629
初級(jí) 203743