我已經了解到,JMS語義規定,即使面對消息代理提供者失敗,也只能保證主題的持久訂戶以持久傳遞模式傳遞消息。 但是對于持久消息的非持久訂戶,該怎么說呢? 沒有持久訂閱者時發送“持久”消息有什么意義?
在查看規范的確切措辭后,我有點不確定。 因此,我查閱了Java消息服務書(Richards,Monson-Haefel和Chappell),以獲取有關保證消息傳遞的更多討論,并查閱ActiveMQ源代碼,并與我的一些同事進行了咨詢。
首先,讓我們看一下規格說明:
根據JMS規范的第4.10節:
大多數客戶應使用產生PERSISTENT消息的生產者。 這樣可以確保從隊列或持久訂閱中傳遞的消息僅一次傳遞一次。
很清楚吧? 使用持久消息傳遞可確保隊列或持久預訂的消息傳遞。
從第6.12節開始:
不可持久訂戶的未確認消息應該能夠在該不可持久訂戶的生命周期中恢復。
因此,現在應該能夠恢復非持久訂戶的未經確認的消息嗎? 我猜是“在那個非持久訂戶的一生中”
但后來成為6.12的一部分:
只有持久訂閱才能可靠地恢復未確認的消息。
和…
為了確保傳遞,TopicSubscriber應該建立持久訂閱。
盡管規范非常清楚地表明(只有效果),只有隊列和持久訂戶才能利用存儲轉發保證的交付,但是我猜我對“非持久訂戶應該能夠在非持久性訂戶的生命周期內恢復”
- 是否根據主題的使用者更改主題的持久性協議(只有在經紀人保留消息并向生產者發送確認后,消息才被視為經紀人的責任)?
- 即使經紀人倒閉,這也意味著嗎? 還是考慮了經紀人的失敗以及非耐久潛艇的訂購期限?
- 當存在用于持久性,非持久性主題的代理網絡時,ActiveMQ會發生什么? 如果網絡中的代理失敗,消息會丟失嗎?
- 向具有非持久訂閱者的主題發送消息“持久”與“非持久”之間的確切區別是什么?
這是保證交付討論中必須考慮的兩個部分。 發布者向代理發送消息的位置,以及消費者從代理接收消息的時間。 對于持久性消息,該協議僅在將消息持久化到存儲后才允許發送方發送消息,并且代理使消息能夠確認。 另一方面,消費者必須在經紀人傳遞消息后確認該消息,說“嘿,我現在將對此消息負責”。 只有這樣,經紀人才會放棄責任并將其從其商店中刪除。 ?
協議是否根據主題的使用者而改變?
因此,對于發送到某個主題的持久消息(目前未考慮任何消費者),規范是否說明在代理發回其確認之前是否應該存儲該消息? 不,不是。 它由有關的JMS代理的實現者來決定。 對于ActiveMQ,如果某個主題上只有非持久訂閱,它將不會保留該消息。
協議的同步性質不會改變,即,如果消息是持久發送的,則會話將認為與代理的交換是同步的,并且它將在繼續之前等待代理的響應,但代理不會實際保留消息。 在ActiveMQ中,如果至少有一個持久訂戶,則此情況會更改。 然后,代理將按照JMS規范保留消息。 ?
這是否意味著即使發生經紀人失敗?
如果代理失敗,則非持久訂閱的生存期確實會中斷。 因此,在代理失敗(或該非持久子項的任何其他終止)的情況下,即使將消息持久發送,也不會將其傳遞給該非持久訂戶。 此外,面對代理的非持久訂閱失敗,將不會重新發送消息。 ?
在經紀人網絡中會發生什么?
消息確實可能丟失。 考慮這個經紀人網絡,其中A-> B-> C和訂閱是從C-> B-> A轉發的。因此,如果我們在A處有一個生產者,生產的主題為“ topic.foo”,而一個非耐用的消費者如果代理B在代理C上從“ topic.foo”消耗,則如果代理B發生故障,此后發送到A的消息將被丟棄。 據A所知,訂閱的生存期已終止。
最后, ?
向具有非持久訂閱者的主題發送消息“持久”與“非持久”之間的確切區別是什么?
根據JMS規范:
出版方式 | 非持久訂戶 | 耐用的訂戶 |
---|---|---|
非持久 | 最多一次(如果不活動則丟失) | 最多一次 |
持久性 | 一次僅一次(如果不活動則丟失) | 一次一次 |
因此,對于非持久性訂戶,非持久性消息將“??最多”傳遞一次,但如果處于非活動狀態(或代理失敗)則將丟失。
對于非持久性訂戶,持久消息將“一次且僅發送一次”,但如果不活動則丟失。 規范的“非活動”部分實際上意味著,如果沒有持久的主題訂閱者,則消息可能會丟失,并且無論消息是持久發送還是非持久發送,都無法保證傳遞。
參考: Christian Posta軟件博客上來自JCG合作伙伴 Christian Posta的主題,JMS規范和ActiveMQ的有保證的消息傳遞 。
翻譯自: https://www.javacodegeeks.com/2012/08/guaranteed-messaging-for-topics-jms.html