java.lang.OutOfMemory

 常見問題 > 錯誤 > 例外 > java.lang.OutOfMemory

好的,這是可管理的。可以配置 ActiveMQ Classic 的幾乎所有記憶體使用情況。首先要確定的是系統的哪個部分記憶體不足。是 JVM、Broker、消費者還是生產者?

此條目是指 ActiveMQ Classic 5.1.x 及更高版本。

記憶體

JVM 記憶體

嘗試使用 bin/activemq 在獨立 JVM 中執行 Broker。請注意腳本傳遞給 Java 可執行檔的預設 JVM 堆大小選項(確切的選項可能取決於您使用的 JVM,範例適用於 Sun JVM)。

  • -Xmx:如果您的作業系統有更多可用記憶體,請考慮增加可供 Broker JVM 使用的總堆記憶體。請注意,JVM 將需要比 -Xmx 值更多的記憶體。執行緒堆疊和 JVM 的內部類別將會消耗額外的記憶體。
  • -Xss:如果您的 Broker JVM 中有大量的執行緒,請考慮使用 -Xss 選項來減少每個執行緒的預設 JVM 堆疊大小。

如果您正在執行嵌入式 Broker 或在第三方容器中,請確保託管 JVM 具有最大堆大小和堆疊大小的適當值。

Broker 記憶體

允許 Broker 使用的記憶體量不是由分配給 JVM 的記憶體量決定的。儘管 Broker 受限於分配給 JVM 的記憶體量,但 Broker 會獨立管理其記憶體。也就是說,Broker 不會 просто 使用 JVM 中的所有記憶體,然後因 OutOfMemory 例外而死掉。這就是您需要了解 systemUsage 記憶體限制和每個目標記憶體限制的地方。

ActiveMQ Classic 中的記憶體以分層方式運作,從 JVM -> Broker -> Broker 功能流動。例如,放置的總目標記憶體限制不能超過 Broker 的記憶體限制。

消費者

除了訊息大小之外,預先提取限制是消費者會記憶體不足的主要原因。減少預先提取值將減少在消費者端記憶體中排隊/儲存的訊息量。

生產者

除非訊息大小超過資源限制,否則生產者不應記憶體不足。生產者可能會注意到 Broker 強制執行記憶體限制的效果,形式為封鎖

其他

將訊息假脫機到磁碟

只有當訊息儲存在記憶體中時,才能快速分派訊息。當消費者速度慢或不存在時,記憶體可能會很快耗盡。
當達到目標的預設記憶體使用量閾值時,Broker(使用訊息游標)會將非持久性訊息假脫機到磁碟。此閾值值是通過的區段指定給 Broker[activemq.xml](xml-configuration) 中的配置。此功能允許生產者在消費者速度慢時繼續傳送訊息,而不會耗盡可用記憶體或還原為[生產者流量控制](producer-flow-control)。如果有多個目標,則組合的預設記憶體閾值可能會過高,並且可能會超過可用記憶體。在這種情況下,減少訊息假脫機到磁碟的記憶體使用「限制」閾值可能是有意義的。另一種選擇是配置「precentUsage」而不是絕對使用「限制」。這樣,記憶體使用量可以限制在可用記憶體的固定百分比內。

可以使用每個目標策略activemq.xml 中指定更具體的每個目標記憶體使用限制。一些額外的範例可以在[訊息游標](message-cursors)參考中找到 map 條目。

執行緒數

預設情況下,ActiveMQ Classic 每個目標使用一個專用執行緒。如果存在大量目標,則會有大量的執行緒及其相關的記憶體資源使用。可以透過使用系統屬性:-Dorg.apache.activemq.UseDedicatedTaskRunner=false,將 ActiveMQ Classic 設定為使用執行緒池。這目前在 activemq 啟動腳本中透過 ACTIVEMQ_OPTS 指定。使用執行緒池可以限制 ActiveMQ Classic 所需的執行緒數量,從而減少記憶體使用量。

非常大的訊息

當您的訊息非常大,以至於您一次只能在記憶體中允許少量訊息時,每個目標策略 maxPageSize 和 lazyDispatch 可以提供幫助。maxPageSize 控制分頁到記憶體中進行分派的訊息量,而 lazyDispatch 使用目前消費者清單的預先提取容量來增強該值。在預先提取為 1、單個消費者和 lazyDispatch 的情況下,一次只會將一個訊息載入記憶體中。

洩漏 JMS 資源

對於消費者或生產者來說,這是最明顯的問題;重複取得 Session 或 MessageProducer 或 MessageConsumer 而不關閉它。對於 java.lang.OutOfMemory,驗證(再次)所有未使用的 JMS 資源是否已釋放是值得的。如果您的應用程式中有多個執行緒,請考慮使用PooledConnectionFactory,因為這將允許 JMS 資源在遵循模式的執行緒之間安全地共享

obtainJmsResource(); 

try 
{ 
    useJmsResource() 
} finally { 
    releaseJmsResource(); 
} 

如果您透過Spring 支援或使用 JMSTemplates 使用 ActiveMQ Classic,請務必檢查您是否沒有落入任何JmsTemplate 陷阱。重新回顧一下如何有效率地使用 JMS 也可能值得。

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