首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

WebLogic JMS Message Pending 狀態根因分析與解決方案

     編輯:Java 相關知識

現象描述

客戶環境中大量 JMS 訊息停留在 receive 狀態,需重啟 JMS Server 或 WebLogic Server 才能被消費。經排查為 WebLogic 潛在 Bug,亦可能與環境(如 NTP 時間同步)有關。

背景知識:receive 狀態與 ACK 機制

  • receive:訊息已被 Consumer 取走,但 Server 端未收到 ACK,訊息無法從 Queue 刪除,且不可被其他 Consumer 消費(Point-to-Point 模型)。
  • ACK 模式決定發送時機:
    • Auto-ack:consumer.receive() 返回前,Client 層自動發送 ACK。
    • Client-ack:應用程式決定何時呼叫 message.acknowledge()。

異常堆疊分析

java.lang.IllegalArgumentException: Delay is negative. at weblogic.timers.internal.TimerManagerImpl.schedule(...) at weblogic.messaging.kernel.internal.ReceiveRequestImpl.<init>(...) at weblogic.jms.backend.BEConsumerImpl.blockingReceiveStart(...) ...

關鍵點:TimerManagerImpl.schedule 因負數 timeout 拋出異常。

WebLogic JMS 接收流程追蹤

  1. JMSConsumer.receive(timeout) → JMSSession.receiveMessage() 建立 FEConsumerReceiveRequest,經 FrontEnd Dispatcher 傳至 BackEnd。
  2. BEConsumerImpl.receive() → blockingReceiveStart() 呼叫 QueueImpl.receive()。
  3. QueueImpl.receive() 初始化 ReceiveRequestImpl,若無匹配訊息,呼叫 addReader() 註冊等待者,並啟動 Timer 等待 timeout。

根因定位

Client 指定 timeout=1,經內部計算變為負數,導致 TimerManagerImpl.schedule() 拋出 IllegalArgumentException。關鍵缺陷:異常拋出前,ReceiveRequestImpl 已被加入 QueueImpl.readerList,但異常處理未將其移除。

連鎖效應:訊息卡在 Pending

  1. 後續 Sender 發送匹配訊息,QueueImpl.match() 發現 readerList 中有等待者,將訊息標記 receive 並移入 Pending List。
  2. 但對應的 JMSConsumer 已因異常關閉,訊息無法 Deliver 至 Client,亦無 ACK 返回。
  3. 訊息永久停留 Pending,直到 Server 重啟清理狀態。

建議對策

  • 升級 WebLogic 修補補丁(確認 Bug 編號)。
  • 檢查 Client/Server 時間同步(NTP),避免 timeout 計算異常。
  • 應用層改用 receiveNoWait() 或明確設定合理 timeout,並加強異常處理與資源清理。
  • 啟用 Spring JMS 異常日誌輸出,避免吞沒關鍵堆疊。

補充:Transaction 狀態訊息

若訊息狀態為 transaction,通常表示發送未完成或處於刪除事務中,屬不同問題域。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved