在本節中,我們將討論連線存活時間 (TTL),並說明 Apache ActiveMQ Artemis 如何處理當機的用戶端以及未正常關閉資源就退出的用戶端。

1. 清理伺服器上的資源

在 Apache ActiveMQ Artemis 用戶端應用程式結束之前,最好使用 finally 區塊以受控制的方式關閉其資源。

以下是一個運作良好的核心用戶端應用程式在 finally 區塊中關閉其會話和會話工廠的範例

ServerLocator locator = null;
ClientSessionFactory sf = null;
ClientSession session = null;

try {
   locator = ActiveMQClient.createServerLocatorWithoutHA(..);

   sf = locator.createSessionFactory();

   session = sf.createSession(...);

   ... do some stuff with the session...
} finally {
   if (session != null) {
      session.close();
   }

   if (sf != null) {
      sf.close();
   }

   if(locator != null) {
      locator.close();
   }
}

以下是一個運作良好的 JMS 用戶端應用程式的範例

Connection jmsConnection = null;

try {
   ConnectionFactory jmsConnectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");

   jmsConnection = jmsConnectionFactory.createConnection();

   ... do some stuff with the connection...
} finally {
   if (connection != null) {
      connection.close();
   }
}

或者使用 Java 的自動關閉功能,可以節省幾行程式碼

try (
     ActiveMQConnectionFactory jmsConnectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
     Connection jmsConnection = jmsConnectionFactory.createConnection()) {
   ... do some stuff with the connection...
}

不幸的是,使用者並不總是編寫運作良好的應用程式,有時用戶端只是當機,因此它們沒有機會清理其資源!

如果發生這種情況,則可能會在伺服器上留下伺服器端資源(如會話)掛起。 如果這些資源未被移除,將導致伺服器上的資源洩漏,並且隨著時間的推移,這會導致伺服器耗盡記憶體或其他資源。

我們必須平衡清理失效用戶端資源的需求,以及有時用戶端與伺服器之間的網路可能會發生故障然後恢復的事實,從而允許用戶端重新連線。 Apache ActiveMQ Artemis 支援用戶端重新連線,因此我們不希望太快清理「失效」的伺服器端資源,否則這將阻止任何用戶端重新連線,因為它將無法在伺服器上找到其舊會話。

Apache ActiveMQ Artemis 使用連線 TTL 使所有這些都可設定。 基本上,TTL 決定伺服器在沒有收到來自用戶端的任何資料時將保持連線存活的時間長度。 用戶端將定期自動傳送「ping」封包,以防止伺服器將其關閉。 如果伺服器在連線 TTL 時間內未收到任何連線上的封包,則它將自動關閉伺服器上與該連線相關的所有會話。

連線 TTL 是使用 connectionTTL 參數在 URI 上設定的。

「不可靠」連線(例如,使用 tcp URL 方案的 Netty 連線)上的連線 TTL 的預設值為 60000 毫秒,即 1 分鐘。「可靠」連線(例如,使用 vm URL 方案的 vm 內連線)上的連線 TTL 的預設值為 -1connectionTTL 的值為 -1 表示伺服器永遠不會在伺服器端逾時連線。

如果您不希望用戶端能夠指定自己的連線 TTL,您可以覆寫伺服器端設定的全域值使用的所有值。 這可以透過在伺服器端設定中指定 connection-ttl-override 屬性來完成。 connection-ttl-override 的預設值為 -1,表示「不覆寫」(即,讓用戶端使用自己的值)。

檢查連線是否存在 TTL 違規的邏輯會定期在代理程式上執行。 預設情況下,檢查每 2,000 毫秒執行一次。 但是,如果需要,可以使用 connection-ttl-check-interval 屬性來變更此設定。

2. 關閉遺忘的資源

如先前所討論,當您完成使用時,務必在 finally 區塊中明確關閉所有核心用戶端會話和 JMS 連線。

如果您未能這麼做,Apache ActiveMQ Artemis 將在垃圾收集時偵測到此問題,並記錄警告(如果您使用的是 JMS,則警告將涉及 JMS 連線)。

然後,Apache ActiveMQ Artemis 將為您關閉連線/用戶端會話。

請注意,記錄檔也會告訴您建立稍後未關閉的 JMS 連線/用戶端會話的使用者程式碼的確切行號。 這將使您能夠找出程式碼中的錯誤並適當地加以修正。

3. 從用戶端偵測故障

在上一節中,我們討論了用戶端如何將 ping 傳送到伺服器,以及伺服器如何清理「失效」的連線資源。 ping 還有另一個原因,那就是讓用戶端能夠偵測到伺服器或網路發生故障。

只要用戶端收到來自伺服器的資料,它就會認為連線仍然處於活動狀態。

如果用戶端在可設定的毫秒數內未收到任何封包,則它會認為連線失敗,並將根據設定的方式啟動容錯移轉,或呼叫任何 FailureListener 執行個體(如果您使用的是 JMS,則呼叫 ExceptionListener 執行個體)。

這是透過在您的用戶端用來連線的 URI 上設定 clientFailureCheckPeriod 參數來控制的,例如 tcp://127.0.0.1:61616?clientFailureCheckPeriod=30000

「不可靠」連線(例如 Netty 連線)上的用戶端故障檢查週期的預設值為 30000 毫秒,即 30 秒。「可靠」連線(例如,vm 內連線)上的用戶端故障檢查週期的預設值為 -1。 值 -1 表示如果未收到來自伺服器的任何資料,用戶端將永遠不會在用戶端端故障連線。 通常,這比連線 TTL 低得多,以允許用戶端在發生暫時性故障時重新連線。

4. 設定非同步連線執行

在伺服器端接收的大多數封包都在遠端處理執行緒上執行。 這些封包表示短暫執行的作業,並且基於效能考量,始終在遠端處理執行緒上執行。

但是,預設情況下,某些類型的封包是使用來自執行緒集區的執行緒執行的,這樣遠端處理執行緒就不會被佔用太久。 請注意,在另一個執行緒上以非同步方式處理作業會增加一些延遲。 這些封包是

  • org.apache.activemq.artemis.core.protocol.core.impl.wireformat.RollbackMessage

  • org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionCloseMessage

  • org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionCommitMessage

  • org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXACommitMessage

  • org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXAPrepareMessage

  • org.apache.activemq.artemis.core.protocol.core.impl.wireformat.SessionXARollbackMessage

若要停用非同步連線執行,請在 broker.xml 中將參數 async-connection-execution-enabled 設定為 false (預設值為 true)。