小菜毛毛技術(shù)分享

          與大家共同成長

            BlogJava :: 首頁 :: 聯(lián)系 :: 聚合  :: 管理
            164 Posts :: 141 Stories :: 94 Comments :: 0 Trackbacks
          現(xiàn)在要求您診斷 WebLogic J2EE 應(yīng)用程序中的性能問題。因為 Java 系統(tǒng)是如此復(fù)雜,所以診斷 WebLogic J2EE 應(yīng)用程序中的性能問題就有點像診斷疑難雜癥。
          為了正確地找到問題所在,您需要對癥狀有全面了解,要做好準備進行大量研究工作,最后您需要制定正確的治療方案。本文討論了 J2EE 應(yīng)用程序性能問題的一些最常見類型和它們產(chǎn)生的原因,以及如何正確地診斷和消除它們的推薦指導(dǎo)原則。


          癥狀
            WebLogic 應(yīng)用程序性能問題的癥狀是什么?您看到的癥狀可以指導(dǎo)您在所有可能的問題中進行搜索。請準備一個筆記本并開始向人們調(diào)查。試著把對問題根本原因的推測和假設(shè)與系統(tǒng)行為的實際證據(jù)分離。下面是一個常見癥狀集的列表: 持續(xù)緩慢:應(yīng)用程序一直特別慢。改變環(huán)境因素(負載、數(shù)據(jù)庫連接數(shù)量)對整體響應(yīng)時間的改變很小。 隨著時間推進越來越慢:系統(tǒng)運行時間越長(負載相對均衡不變的情況下),就變得越慢。有可能是(最后)達到了某個閾值,系統(tǒng)被鎖定或者由于大量錯誤而崩潰。 隨著負載增加越來越慢:每增加一個額外用戶,應(yīng)用程序就變得越慢。如果用戶離開系統(tǒng),系統(tǒng)就“冷卻下來”,恢復(fù)正常。 零星的掛起或者異常錯誤:偶爾(可能由于負載或某些其它原因),在頁面無法完成或者出現(xiàn)追蹤到異常和堆棧的錯誤頁時,用戶會看到掛起的情況。掛起的數(shù)量可能不同,但總是無法完全消除,甚至在強化 (“burn in”) 期間之后也是如此。 可以預(yù)見的鎖定:首先出現(xiàn)一些掛起或錯誤,然后加速出現(xiàn),直到系統(tǒng)完全被鎖定。通常這些問題可以通過“重新啟動來管理”的方式解決。 突然混亂:系統(tǒng)一直運行正常,相當一段時間里(可能一個小時,也可能是三天)性能都還差強人意,但是“突然某個時候,根本沒有任何原因的”,系統(tǒng)開始出現(xiàn)大量錯誤,或者被鎖定。

          為什么問題診斷如此復(fù)雜? 軟件開發(fā)網(wǎng)
            對于 WebLogic 應(yīng)用程序的某個具體應(yīng)用模式來說,沒有既定的公式可以用來推導(dǎo)出它的性能(在嚴格的實時工程當中,速度單調(diào)分析這類技術(shù)確實可以做這項工作,但是在本文里還是讓我們忘記它吧)。網(wǎng)絡(luò)上是否存在另外一個系統(tǒng)正在密集使用一個共享的后端服務(wù),對于實際產(chǎn)生的性能有很大影響。性能也許還取決于 JDBC 驅(qū)動程序版本和數(shù)據(jù)庫的正確匹配。也許開發(fā)人員三年前寫的一些代碼恰巧在這個時候才出現(xiàn)特定類型的異常,而您急切需要的解決問題回饋,卻恰恰包含在這個異常里。
            從本質(zhì)上說,典型業(yè)務(wù)系統(tǒng)的性能是由成千上萬交互的變量和決策共同作用的結(jié)果。就像人體一樣,有太多連鎖著的部分和過程,所以很難理解系統(tǒng)的整體。因此我們進行了簡化,并求助于拱形模式。

          疾病
            您看到的癥狀的根本原因是什么?它是初級流行性感冒或者是肺炎的開始嗎?是應(yīng)用程序內(nèi)部的底層問題還是它所在的 JVM 外部的問題?請參閱表 1 中應(yīng)用程序性能低下的一些最常見原因。

          http://www.mscto.com

           

          表1

           

          毛病 描述 癥狀 原因或治法 線性內(nèi)存泄漏 每單位(每事務(wù)、每用戶等)泄漏造成內(nèi)存隨著時間或負載線性增長。這會隨著時間或負載增長降低系統(tǒng)性能。只有重啟才有可能恢復(fù)。 隨著時間越來越慢
          隨著負載越來越慢 雖然可能有多種外部原因,但最典型的是與資源泄漏有關(guān)(例如,每單位數(shù)據(jù)的鏈表存儲,或者沒有回收的回收/增長緩沖區(qū))。 指數(shù)方式內(nèi)存泄漏 雙倍增長策略的泄漏造成系統(tǒng)內(nèi)存消耗表現(xiàn)為時間的指數(shù)曲線 隨著時間越來越慢
          隨著負載越來越慢 通常是由于向集合(Vector,HashMap) 中加入永遠不刪除的元素造成的。 糟糕的編碼:無限循環(huán) 線程在 while(true) 語句以及類似的語句里阻塞。 可以預(yù)見的鎖定 您需要對循環(huán)進行大刀闊斧的刪剪。 資源泄漏 JDBC 語句,CICS 事務(wù)網(wǎng)關(guān)連接,以及類似的東西被泄漏了,造成對 Java 橋接層和后端系統(tǒng)的影響。 隨著時間越來越慢
          可以預(yù)見的鎖定
          突然混亂 通常情況下,這是由于遺漏了 finally 塊,或者更簡單點,就是忘記用 close() 關(guān)閉代表外部資源的對象所造成的。 外部瓶頸問題 后端或者其他外部系統(tǒng)(如鑒權(quán))越來越慢,同樣減緩了 J2EE 應(yīng)用服務(wù)器和應(yīng)用程序 持續(xù)緩慢
          隨著負載越來越慢 咨詢專家(負責(zé)的第三方或者系統(tǒng)管理員),獲取解決外部瓶頸問題的方法。 外部系統(tǒng) J2EE 應(yīng)用程序通過太大或太多的請求濫用后端系統(tǒng)。 持續(xù)緩慢
          隨著負載越來越慢 清除冗余的工作請求 ,成批處理相似的工作請求,把大的請求分解成若干個更小的請求,調(diào)整工作請求或后端系統(tǒng)(例如,公共查詢關(guān)鍵字的索引)等。 糟糕的編碼:CPU密集的組件 這是 J2EE 世界中常見的感冒。一些糟糕的代碼或大量代碼之間一次糟糕的交互,就掛起了 CPU,把吞吐速度減慢到爬行的速度。 持續(xù)緩慢
          隨著負載越來越慢 典型的解決方案就是數(shù)據(jù)高速緩存或者性能計數(shù)。 中間層問題 實現(xiàn)得很糟糕的橋接層(JDBC 驅(qū)動程序,到傳統(tǒng)系統(tǒng)的 CORBA 連接),由于對數(shù)據(jù)和請求不斷的排列、解除排列,從而把所有通過它的流量減慢到爬行速度。這個毛病在早期階段很容易與外部瓶頸混淆。 持續(xù)緩慢


          隨著負載越來越慢 檢查橋接層和外部系統(tǒng)的版本兼容性。如果有可能,評估不同的橋接供應(yīng)商。如果重新規(guī)劃架構(gòu),有可能完全不需要橋接。 內(nèi)部資源瓶頸:過度使用或分配不足 內(nèi)部資源(線程、放入池的對象)變得稀缺。是在正確使用的情況下加大負載時出現(xiàn)過度使用還是因為泄漏? 隨著負載越來越慢
          零星的掛起或異常錯誤 分配不足:根據(jù)預(yù)期的最大負載提高池的最大尺寸。過度使用:請參閱外部系統(tǒng)的過度使用。 不停止的重試 這包括對失敗請求連續(xù)的(或者在極端情況下無休止的)重試。 可以預(yù)見的鎖定
          突然混亂 可能就是后端系統(tǒng)完全宕機。在這里,可用性監(jiān)控會有幫助,或者就是把嘗試與成功分開。 線程:阻塞點 線程在過于積極的同步點上備份,造成交通阻塞。 隨著負載越來越慢
          零星的掛起或異常錯誤
          可以預(yù)見的鎖定
          突然混亂 可能同步是不必要的(只要重新設(shè)計),或者比較外在的鎖定策略(例如,讀/寫鎖)也許會有幫助。 線程:死鎖/活動鎖 最普遍,這是您基本的“獲得順序”的問題。 突然混亂 處理選項包括:主鎖,確定的獲得順序,以及銀行家算法。

          測量關(guān)鍵的統(tǒng)計指標


            當您負責(zé)診斷問題的時候,您應(yīng)當能夠跟蹤關(guān)于您的 WebLogic 應(yīng)用程序健康情況的關(guān)鍵統(tǒng)計指標。您能測量什么?有什么工具可以提供幫助呢?

           

          使用的全部內(nèi)存:在不同級別上 (JVM 堆棧,操作系統(tǒng)),Java 堆棧 profiler 對堆棧的正確使用提供了可見性;像 top ,vmstat 以及 Windows Perfmon 這樣的工具在操作系統(tǒng)級別上為內(nèi)存使用提供可見性。察看 Java 堆棧的一個簡單的聚合視圖,請打開—verbose:gc 開關(guān)(如果在您的 JVM 上可以使用的話)。 CPU 時間:合并(可以通過使用 top 等方式得到)每個組件或每種方法。其中某些指標可以通過 WebLogic 管理控制臺得到。也可以通過 Java profile 使用它們。 計時 (a.k.a.“實” 時):每事務(wù),每組件,每方法;可以按統(tǒng)計平均值或單獨的數(shù)據(jù)點查看。Java profiler 可以產(chǎn)生一些這樣的數(shù)據(jù),但是使用程序監(jiān)控解決方案可能是您的最佳選擇。 內(nèi)部資源:
          分配的數(shù)量,使用的數(shù)量,等待的客戶數(shù)量,獲得資源的平均等待時間,使用資源平均消耗的時間,使用資源完成請求工作時使用的平均時間。應(yīng)用程序服務(wù)器通常會給出這些數(shù)字的最小可視性。 外部資源:分配的數(shù)量,使用的數(shù)量,等待的客戶數(shù)量,平均等待時間,加上對這些外部系統(tǒng)的直接測量(例如查看它能多快完成請求的工作)。不要忘記運行應(yīng)用程序服務(wù)器的操作系統(tǒng)和硬件也是“外部資源”-例如,是否您使用了太多的進程或端口?可以用兩種形式測試這些資源—從 JVM 內(nèi)部測試提供資源的橋接層,用外部資源本身的工具測量外部資源。 網(wǎng)絡(luò)應(yīng)用:帶寬使用,延遲。雖然操作系統(tǒng)自帶的工具(例如 netstat)也有助于做這些工作,但是網(wǎng)絡(luò)嗅探器設(shè)備可以深入了解這些信息。 系統(tǒng)狀態(tài):用線程清除,日志和跟蹤文件,堆棧跟蹤等等。或者在更深層次上,就像調(diào)試器中查看的那樣使用變量的值。

          實驗工作
            有的時候,在一次標桿運行中獲得的數(shù)據(jù),不足以揭示答案。那么找到答案的機會就在于您還有些有限的預(yù)算,可以運行試驗或者做實驗工作,來完成診斷。您可以運行什么類型的試驗?zāi)兀磕梢孕薷摹⒂^察什么變量呢?

          http://www.mscto.com

           

          嘗試觀察系統(tǒng)行為在一段時間上的變化。應(yīng)用一個衡定的負載,并觀察您的指標隨時間發(fā)生的變化。您可能會看到某些趨勢,短則一小時就可看到,長則二三天。例如,您可以看到內(nèi)存使用隨著時間而增長。隨著使用的內(nèi)存數(shù)量達到上限, JVM 花在搜索垃圾上的時間和操作系統(tǒng)花在分配內(nèi)存頁面上的時間開始減少用戶事務(wù)的整體響應(yīng)時間。當拋開 GC 的時候,垃圾搜集的整個過程可能過長,從而造成執(zhí)行中的事務(wù)超時和異常。現(xiàn)在可以開始查找資源泄漏或內(nèi)存泄漏了。 嘗試在系統(tǒng)上改變負載。 采用三到四種工作負載(例如,10個,50個和100個用戶),并搜集每個負載的數(shù)據(jù)。分析一下您對這些負載的測量情況。例如,您可能發(fā)現(xiàn),當您的賬戶登錄 servlet 的響應(yīng)時間無論如何都會低于 50 毫秒的時候,計算銷售稅的 EJB 卻隨著用戶數(shù)據(jù)的增長,速度呈線性下降。如果這個 EJB 性能在負載下的差異能解釋整體響應(yīng)時間性能在負載下的增長,那么現(xiàn)在就是深入分析這個組件的時候了。謹記一定還要把負載恢復(fù)原狀,并查看系統(tǒng)是否復(fù)原。 嘗試把系統(tǒng)分成小單元,針對每個單元輪流進行壓力測試。 選擇一個或多個坐標系對系統(tǒng)進行劃分。主要的一個是系統(tǒng)面上的層:負載均衡器、Web 服務(wù)器、WebLogic Server,以及后端。其它示例包括用戶賬戶,內(nèi)部組件,事務(wù)類型,以及單獨的頁面。假設(shè)您選擇了用戶賬戶。在用戶 A 的賬戶下運行一些負載,然后再在用戶 B 的賬戶(應(yīng)當非常不同)下運行某些負載;比較兩次運行間不同的測量結(jié)果。或者,輪流選擇您使用的后端系統(tǒng),分別對使用每個后端系統(tǒng)比較重的應(yīng)用程序組件進行壓力測試。具體要選擇哪個坐標進行劃分,完全取決于您要證明或者否定哪個假設(shè)。下面是一些具體想法:
            - 如果某個用戶的登錄看起來造成了問題,那么有可能是這個用戶賬戶檔案(例如,裝入 2,000 個訂單的完整采購歷史),或者可能是他使用系統(tǒng)的方式(例如,頁面訪問的順序,或者他用來查找某個文檔的查詢字符串的正確性)。
            - 如果您使用的是一個集群系統(tǒng),請嘗試以單臺機器為單位劃分。盡管盡了最大努力,有的時候還會有一些機器沒有安裝最新的應(yīng)用服務(wù)器或者操作系統(tǒng)補丁,這就會造成不同的性能特征。而且,還請注意負載均衡器,或者保姆進程,查看它們是否公平地分配了工作并跟蹤了進入請求。

          診斷:測試您的推測
            在這個時候,您應(yīng)當已經(jīng)有了足夠的信息,可以形成關(guān)于性能瓶頸原因的推測了(請參閱表 1)。為了驗證您的推測是否正確或者在多個備選的推測之間進行篩選,您需要分析更多的信息或者在系統(tǒng)上運行更多的標桿測試。這里是一些可以幫助您的指導(dǎo)意見:
          區(qū)分糟糕的編碼(或者是應(yīng)用程序組件或者是橋接層)和瓶頸 (內(nèi)部的或外部的),請查看整體的 CPU 使用情況。如果它在負載下沒變化,但是整體響應(yīng)時間變化了,那么就是應(yīng)用程序花費了它的大多數(shù)時間來等待。 僅僅是因為好像是外部資源的問題,不代表您就可以立刻把責(zé)任推到資源上。 例如,分層或聯(lián)網(wǎng)的問題,也能造成數(shù)據(jù)庫看起來很慢,雖然實際上它并不慢。或者,更簡單一點,您對數(shù)據(jù)庫的請求可能是不合理的(每次用戶登錄的時候,都要進行三個表之間的 200 萬行記錄合并)。應(yīng)當一直把橋接層的響應(yīng)時間(例如,JDBC 驅(qū)動器)和資源提供的時間或者工具提供的時間進行比較(例如,DBA Studio)。 結(jié)構(gòu)化的圖表有助于您理解系統(tǒng)內(nèi)部的整體交互,但是不要忘記地圖并不是領(lǐng)地。.編碼錯誤或者對架構(gòu)意圖的誤解,有可能使系統(tǒng)的實際行為與期望的行為不同。請相信性能工作提供的實際數(shù)據(jù),而不要相信一個聲稱“每個用戶事務(wù)將只會發(fā)布一個 SQL 語句”這樣的文檔。 使用 Occam 軍刀。 假設(shè)您有兩個備選推測,一個是:在 200 萬行代碼里,有一個編碼糟糕的組件,直到上周這個組件才集成進來;另一個是 JVM 的即時編譯器生成了糟糕的機器碼,破壞了這個變量的內(nèi)存完整性。除非您有具體的數(shù)據(jù)來證實,否則(我已經(jīng)看到了第二種情況發(fā)生),請更詳細地檢查第一個假設(shè)。J2EE 系統(tǒng)確實容易出錯,但是不要讓這一點就妨礙您先測試一個更簡單的假設(shè)。 日志文件中沒有錯誤不代表不存在錯誤。 有許多原因可以造成不在日志里寫下異常;可能是因為程序員認為某件事“永遠不會發(fā)生”,于是就排除了這個異常;也可能是因為某些組件可以使用故障恢復(fù)機制,所以就沒有記錄第一次故障。

          示例診斷
            讓我們來實際研究一個示例。您的 WebLogic 應(yīng)用程序表現(xiàn)出在負載下越來越慢的癥狀。您加入的用戶越多,系統(tǒng)越慢。一旦消除負載,系統(tǒng)就冷靜下來,沒有任何后遺癥。您對這一主要癥狀進行測試,發(fā)現(xiàn)并得到圖 2 所示的以下結(jié)果(時間測量針對的是單一典型事務(wù)的端到端完成時間)。

          表2

          負載(用戶數(shù)) 來回用時(毫秒) 10 300 50 471 100 892 150 1067

          應(yīng)用程序性能在負載下越來越慢

          http://www.mscto.com

           

            您形成了幾個假設(shè)。也許這里的毛病是一個糟糕編碼的組件,也許是后端系統(tǒng)的瓶頸。它可能是一個同步阻塞點。您怎樣才能分清它們的不同呢?假設(shè)您還測試了應(yīng)用程序服務(wù)器在負載運行期間的CPU整體使用情況,并得到了表 3 所示的結(jié)果。

          表3

           

          負載(用戶數(shù)) 來回用時(毫秒) 整體 CPU 時間(%) 10 300 30 50 471 33 100 892 37 150 1067 41

          問題看起來好像是“等待”瓶頸

           

            現(xiàn)在看起來,系統(tǒng)不是 CPU 密集型的,這就是說它的多數(shù)時間都花在等待上了。那么是它的內(nèi)部(例如,同步交通阻塞)或外部(緩慢的數(shù)據(jù)庫)的問題?好,讓我們假設(shè)我們還稍微多搜集了一些數(shù)據(jù),如表 4 所示。

           

          表4

          負載(用戶數(shù)) 等待數(shù)據(jù)庫連接的線程數(shù)量 JDBC 查詢用時(毫秒) 10 2 58 50 3 115 100 3 489 150 4 612


          問題是否出在一個緩慢的 SQL 語句上呢?

          現(xiàn)在看起來并不是內(nèi)部等待數(shù)據(jù)庫連接的瓶頸,相反,好像是 JDBC 查詢本身的問題。JDBC 查詢不僅隨整體事務(wù)時間的不同而不同,而且它糟糕的性能還解釋了整體性能糟糕的原因。但是,我們還不能完全確定。您仍然還有三個主要的假設(shè)要排序:是否數(shù)據(jù)庫本身慢?應(yīng)用程序是否對數(shù)據(jù)庫進行了不合理的請求?或者問題是不是出在應(yīng)用程序和數(shù)據(jù)庫之間的某個層上?您拿出數(shù)據(jù)庫供應(yīng)商專用的工具,從它的角度查看響應(yīng)時間。假設(shè)您看到如表 5 所示的數(shù)字。

          表5

           

          負載(用戶數(shù)) JDBC 查詢計時(毫秒) DB SQL 執(zhí)行的時間(毫秒) 10 58 43 50 115 97 100 489 418 150 612 589
          實際是數(shù)據(jù)庫中的 SQL 語句慢

            如果您沒有看到這條信息,那么您可能要返回 JDBC 驅(qū)動程序,期待能夠發(fā)現(xiàn)其中的某些同步問題(請記住,CPU 沒有被抑制)。幸運的是,在這個案例里,您已經(jīng)把具體問題的范圍縮小到數(shù)據(jù)庫查詢上。找出查詢請求是否足夠合理,需要一些相關(guān)領(lǐng)域的知識,需要熟悉系統(tǒng),但是在這個案例里,它也許就是發(fā)現(xiàn)查詢把非索引字段和外鍵進行了比較。您和 DBA 協(xié)作,它修改索引方案,讓查詢變得更快,而您則找到了您的藥方。

          結(jié)束語
            診斷 WebLogic J2EE 應(yīng)用程序的性能瓶頸是一個艱苦的旅程。請隨時保持清醒,把事實與推測分開,總是用實際的證據(jù)來確認您的推測。我希望給您帶來了思考和實踐問題的一些有用的想法的分類。就像調(diào)試,這仍然是一項不明確的藝術(shù),但是深思熟慮會帶您走出困境。祝您好運!

           

          關(guān)于作者
            John Bley 是 Wily Technology 的軟件工程師。他有豐富的 Java 編程和架構(gòu)經(jīng)驗。為了撰寫本文,他總結(jié)了 Wily 的企業(yè)客戶的經(jīng)驗,Wily負責(zé)管理復(fù)雜的 J2EE 環(huán)境。(更多)
          原文出處 http://www.sys-con.com/story/?storyid=43024&DE=1

          posted on 2010-02-05 13:32 小菜毛毛 閱讀(960) 評論(0)  編輯  收藏 所屬分類: 性能優(yōu)化
          主站蜘蛛池模板: 梨树县| 突泉县| 泾川县| 策勒县| 礼泉县| 朔州市| 汝州市| 江油市| 昔阳县| 东乡县| 怀宁县| 凌海市| 托克托县| 鹤峰县| 宜黄县| 酉阳| 西充县| 夏邑县| 连江县| 岚皋县| 从化市| 虹口区| 舟曲县| 昆山市| 玉树县| 辽中县| 丹棱县| 隆林| 瑞昌市| 毕节市| 台湾省| 江阴市| 新安县| 石渠县| 武乡县| 定州市| 赣榆县| 朝阳县| 康保县| 布尔津县| 黑河市|