JmsTemplate 的陷阱

連線能力 > 容器 > Spring 支援 > JmsTemplate 的陷阱

要記住的是,JmsTemplate 的設計是為了在 EJB 中使用 EJB 容器的 JMS 池化抽象。因此,每個方法通常都會建立連線、會期、生產者或消費者,執行一些操作,然後再次關閉所有這些資源。其想法是使用 J2EE 容器的池化機制來池化底層的 JMS 資源。如果未使用 EJB 容器提供的池化 JMS 提供者,這是使用 JMS 的最糟糕的方式;因為通常建立/關閉連線、生產者/消費者都會導致與 JMS 代理進行請求-回應。

使用者故事

我們曾經在 ActiveMQ Classic 中遇到一個錯誤,如果您在幾秒鐘內建立 65535 個 MessageProducer 實例,我們會在代理中拋出例外。在短時間內建立那麼多生產者(每個要傳送的訊息一個)是很愚蠢的事情 - JMS 的設計是讓生產者和消費者等資源預先建立好,並在許多訊息交換中重複使用。這個錯誤是由一個在底下沒有 JMS 池的情況下使用 JmsTemplate 的使用者發現的。至少這幫助我們發現了這個錯誤,我很高興地說這個錯誤現在已經修復了,但它對他們的效能沒有太大的幫助。

您應該僅將 JmsTemplate 與池化的 JMS 提供者一起使用。在 J2EE 1.4 或更高版本中,通常意味著基於 JCA 的 JMS 連線工廠。如果您在 EJB 中,請確保您使用 J2EE 容器的 ConnectionFactory,永遠不要使用普通的連線工廠。如果您不在 EJB 內部,則應使用我們的 PooledConnectionFactory,這樣資源就會被妥善地池化。如果您需要參與 XA 交易,請研究我們基於 Spring 的 JCA 容器

我還看到人們犯的另一個陷阱是在其中一個 SessionCallback 方法中建立 MessageConsumer,然後想知道為什麼沒有收到訊息。在 SessionCallback 被呼叫後,會期將會關閉;這也會關閉您的消費者。因此,如果您想要建立 MessageConsumer,您應該自己建立連線、會期和消費者。

我還看到的另一個問題是人們使用 JmsTemplate.receive() 方法;正如我上面所說的,如果您不在 EJB 中使用 J2EE 容器的 ConnnectionFactory,則每次 receive() 方法都會建立和關閉連線、會期和消費者。如果沒有使用池化,這一切都很好 - 如果速度慢得令人痛苦 - 但請注意,在沒有池化的情況下,此機制很可能會遺漏訊息。如果您在具有以 NON_PERSISTENT 傳遞模式傳送的訊息的主題上使用,則您很可能會遺漏訊息,因為每次 receive() 呼叫都是一個全新的消費者,它不會收到在消費者存在之前傳送的任何訊息。為了有效率地接收訊息,您應該使用 Spring 的 MessageListenerContainer

4.x 版的新功能

在 ActiveMQ Classic 4.x 中,我們有一個稱為 訂閱復原策略的新功能,即使在非持久傳遞模式下,也允許新的消費者回到過去並接收在視窗內傳遞的訊息(固定數量的 RAM 或時間視窗)。例如,如果您的代理當機,您有 2 分鐘的時間重新連線到另一個代理,並且不會遺漏任何訊息 - 即使沒有持久傳遞。

使用 JmsTemplate 的建議

Apache、ActiveMQ、Apache ActiveMQ、Apache 羽毛標誌和 Apache ActiveMQ 專案標誌是 The Apache Software Foundation 的商標。版權所有 © 2024,The Apache Software Foundation。依據 Apache License 2.0 授權。