<b></b>
作者介紹
王超,國内第一位中間件oracle ace,東方宏達中間件技術總監,原oracle|bea 資深中間件現場支援工程師,14年現場支援工作經驗,weblogic 6.1/7.0/8.1/9.2/10.3/11g/12c、tuxedo技術認證專家。深厚的中間件架構規劃、性能調優、問題解決經驗,常年為為電信、金融等領域客戶提供現場技術支援。
1.1、概述
weblogic伺服器執行線程耗盡後就不再響應後續請求,weblogic即出現挂起現象。
weblogic線程耗盡産生的原因有多種,一般而言線程耗盡是由于線程在争奪某種資源。當一種資源處于缺少狀态,比如資料庫jdbc連接配接池的達到最大連接配接數,就會導緻後續的業務線程都卡在等待擷取jdbc的連接配接上,最終導緻伺服器無法響應後續的服務請求。
1.2、常見線程耗盡原因
weblogic伺服器線程耗盡,最常見的幾種原因如下:
weblogic、jdk自身的bug
業務系統中采用的開源軟體的bug
主機硬體到達上限瓶頸,無法承擔更多的負載
資料庫jdbc連接配接池耗光,後續業務線程無法擷取到可用jdbc連接配接而一直處于等待狀态
應用程式同步調用。比如業務線程a執行的過程中鎖定了資源1,而由于同步調用的原因導緻其他業務線程不得不一直無限等待資源1的鎖被釋放。
業務系統沒有使用weblogic線程池,而使用自定義的線程池。當自定義線程池全部被占用,就會導緻沒有線程可用于新工作。
線程都處于等待rjvm、rmi響應
應用配置不合理,比如設定了錯誤的jsp pagecheckseconds參數等
1.3、判斷條件
在出現以下情況時懷疑weblogic伺服器線程耗盡:
伺服器不響應新的請求
請求逾時
請求處理的時間越來越長(其最終結果可能是挂起)
通常,伺服器挂起不會表現為伺服器崩潰,但伺服器挂起之後可能會崩潰。
1.4、收集資訊
當伺服器挂起時,首先使用 java weblogic.admin t3://server:port ping 來 ping 該伺服器。如果伺服器能夠響應此 ping,則可能是應用程式所使用的線程池耗盡而不是伺服器自身。
weblogic server 在8.1版本之前使用“default”線程池響應用戶端服務請求,在9.0版本以後使用default (self-tuning)線程池響應用戶端服務請求。這些是在發生線程耗盡時應當檢查的線程池。通常情況下,用收集jvm的thread dump的辦法來分析線程池運作資訊。
linux / unix系統
任何weblogic版本均可使用 kill -3 建立診斷問題所需的 thread dump。確定在每個伺服器上執行幾次,每次間隔大約 3 到 5秒,以幫助診斷死鎖問題。
在weblogic 9.2版本或者是更高的版本中,可以直接通過使用jdk的jstack指令來收集thread dump資訊。
windows作業系統
任何weblogic版本均可使用 - 來建立診斷問題所需的 thread dump。確定在每個伺服器上執行幾次,每次間隔大約 3 到 5 秒,以幫助診斷死鎖問題。
1.5、實施步驟
收集作業系統、weblogic運作相關基本資訊
收集出現線程耗盡時間段weblogic運作日志
采集thread dump
在伺服器上快速分析thread dump,初步定位線程耗盡問題
重新開機線程耗盡weblogic伺服器,使其盡快對外提供服務
将采集到的thread dump下載下傳到本地,進行詳細的離線分析
1.6、分析thread dump
weblogic除了包含業務系統所使用的執行線程池以外,還包括listenthread線程池、socket reader線程池以及自定義線程池等等。由于weblogic軟體是非常複雜的企業軟體,是以在分析的時候,我們不但需要關注業務執行線程池,同時也需要關注其他線程池。weblogic線程池簡易圖示如下:
thread dump線程轉儲是将目前jvm包含的所有的線程的運作狀态的一個映像,包含了:
各個線程的棧 (stacktrace)
線程目前的狀态
線程名字
線程号(tid)以及對應的native thread id (nid) 等資訊
分析weblogic伺服器線程耗盡的最有用的辦法是分析一系列 的thread dump。一系列 thread dump(一般每隔3 到 5 秒進行三個或更多 thread dump)可以幫助分析每個線程從一個 thread dump 到另一個 thread dump 過程中的狀态變化或所缺少的變化。weblogic伺服器線程耗盡導緻伺服器挂起後,伺服器的 thread dump 一般顯示線程狀态從第一個 thread dump 到最後一個 thread dump 中變化很小。
在 thread dump 中檢視的内容
所有請求都通過 listenthread 進入 weblogic server。如果 listenthread 丢失,就無法接收任何工作,是以也無法完成任何工作。确認在 thread dump 中存在 listenthread。listenthread 應當在 socketaccept 方法中。下面示例說明監聽線程 (listen thread) 的形式。
socket reader 線程接受來自監聽線程隊列的傳入請求,并将該請求放入執行線程隊列。如果 thread dump 中沒有 socket reader 線程,則在某個地方存在導緻 socket reader 線程消失的錯誤。應當始終保持至少有三個 socket reader 線程。一個 socket reader 線程一般用于輪詢功能,另外兩個用于處理請求。下面是一個 thread dump 示例中的 socket reader 線程。
通常,業務代碼使用的是weblogic預設的執行線程池,在weblogic 8.1之前以“default”命名,在9.x以後以“weblogic.kernel.default(self-tuning)”命名。檢視執行線程的狀态,主要看thread dump裡面的state的值。同時,為了更快的定位問題,weblogic伺服器會将運作時間超過600秒的執行線程标記為“stuck”狀态,如下所示:
java中線程的狀态
thread dump中,java線程的各種狀态如下:
狀态
說明
new
初始狀态。線程剛剛被建立,并且start()方法還未被調用
runnable
運作狀态。表示線程正在java虛拟機中執行,但是可能正在等待作業系統的其他資源,比如cpu
blocked
阻塞狀态。表示線程正在等待螢幕鎖。表示線程正在等待擷取螢幕鎖,以便進入同步方法或者同步代碼快,也有可能是從wait()方法被喚醒而等待再次進入同步方法或者同步代碼塊
waiting
等待狀态。表示目前線程需要等待其他線程執行一些特殊操作,比如目前線程調用了a.wait()方法,它正在等待其他線程調用a.notify或a.notifyall方法;如果目前線程調用了threada.join(),那麼它在等待threada執行完成
timed_waiting
逾時等待。與waiting的不同在于,該狀态有逾時時間
terminated
終止狀态,表示目前線程已經執行完畢
線程狀态的詳細介紹請參考java源代碼的thread内部類:state。
其中線程狀态中waiting與timed_waiting差別如下:
調用以下三個方法會進入waiting狀态:
object.wait() 不設定逾時時間
thread.join() 不設定逾時時間
locksupport.park() 不設定逾時時間
調用下面的方法會進入timed_waiting狀态:
object.wait(time)
thread.join(time)
thread.sleep(time)
locksupport.parknanos(time)
locksupport.parkuntil(time)
1.6、相關腳本
收集thread dump的示例腳本如下:
<b>本文來自雲栖社群合作夥伴"dbaplus",原文釋出時間:2016-08-16</b>