HBCZT信息中心Weblogic Server性能調優建議

調優背景

HBCZT 信息中心使用IBM X366服務器Windows2003運行其基於J2EE1.4技術的應用系統。另外運行一個基於COM技術的數據採集應用程序。該程序客戶端讀入用戶填 寫的xls格式表格文件信息,並通過該程序將XLS內容封裝成爲XML並打包ZIP後發送到數據採集程序的服務器端,服務器端接受到文件後,對該ZIP包 進行解包、並對解包後的XML信息進行解析、使用SQL逐條將記錄插入到Oracle數據庫中。數據庫連接池已經設置爲20,但批量數據插入數據庫的時候 (數據量至少500000條記錄,一般情況5000000條記錄)導致數據庫異常緩慢。客戶希望找到系統瓶頸,並提出相應性能調優建議。

1、總體思路

硬件調優、操作系統調優,數據庫調優 略!我們假設都已經是最佳狀態。由於本人負責WebLogic部分的調優,所以以下思路與內容均爲WebLogic方面。特此說明

J2EE 應用架構環境下的系統調優,首先我們一般會從應用程序出發,去審覈代碼,做到代碼級的優化,然後再調整應用服務器(BEA WebLogic8.1)和數據庫 (Oracle9i)的參數,最後當然是調整操作系統和網絡的性能(包括硬件升級)。這是一種MDA的先進做法。誠然,在這樣一個政務項目中,不可能完全 按照這個思路來做,我們把目標首先定位在應用系統所在的應用服務器(BEA WebLogic8.1)上,通過對BEA WebLogic8.1的參數進行設置,使WebLogic8.1能夠在最優化的環境中去運行其系統,然後對ORACLE數據的參數進行優化設置,最後進 行性能測試再找出導致性能瓶頸所在的SQL代碼或JAVA程序,考量其修改的可行性,並進行最終問題優先級認定,與瓶頸模塊進行協商解決性能問題。當然, 一般情況下我見過的案例都是出現了性能問題後纔想到調優,而且一般都是先進行系統參數調整,實在解決不了纔會對代碼進行檢查.實際上,我們應當將代碼級的 調優放在應用設計時來做,測試生產時修改代碼將是一件極其痛苦的事情。

下表爲一般性J2EE性能調優的參照情況一覽表,供參考。

毛病

描述

症狀

原因或治法

線性內存泄漏

 

每單位(每事務、每用戶等)泄漏造成內存隨着時間或負載線性增長。這會隨着時間或負載增長降低系統性能。只有重啓纔有可能恢復。 隨着時間越來越慢
隨着負載越來越慢
雖然可能有多種外部原因,但最典型的是與資源泄漏有關(例如,每單位數據的鏈表存儲,或者沒有回收的回收/增長緩衝區)
指數方式內存泄漏

 

雙倍增長策略的泄漏造成系統內存消耗表現爲時間的指數曲線 隨着時間越來越慢
隨着負載越來越慢
通常是由於向集合(VectorHashMap) 中加入永遠不刪除的元素造成的。
糟糕的編碼:無限循環

 

線程在 while(true) 語句以及類似的語句裏阻塞。 可以預見的鎖定 您需要對循環進行大刀闊斧的刪剪。
資源泄漏

 

JDBC 語句,CICS 事務網關連接,以及類似的東西被泄漏了,造成對 Java 橋接層和後端系統的影響。 隨着時間越來越慢
可以預見的鎖定
突然混亂
通常情況下,這是由於遺漏了 finally 塊,或者更簡單點,就是忘記用 close() 關閉代表外部資源的對象所造成的。
外部瓶頸問題

 

後端或者其他外部系統(如鑑權)越來越慢,同樣減緩了 J2EE 應用服務器和應用程序 持續緩慢
隨着負載越來越慢
諮詢專家(負責的第三方或者系統管理員),獲取解決外部瓶頸問題的方法。
外部系統

 

J2EE 應用程序通過太大或太多的請求濫用後端系統。 持續緩慢
隨着負載越來越慢
清除冗餘的工作請求 ,成批處理相似的工作請求,把大的請求分解成若干個更小的請求,調整工作請求或後端系統(例如,公共查詢關鍵字的索引)等。
糟糕的編碼:CPU密集的組件

 

這是 J2EE 世界中常見的感冒。一些糟糕的代碼或大量代碼之間一次糟糕的交互,就掛起了 CPU,把吞吐速度減慢到爬行的速度。 持續緩慢
隨着負載越來越慢
典型的解決方案就是數據高速緩存或者性能計數。
中間層問題

 

實現得很糟糕的橋接層(JDBC 驅動程序,到傳統系統的 CORBA 連接),由於對數據和請求不斷的排列、解除排列,從而把所有通過它的流量減慢到爬行速度。這個毛病在早期階段很容易與外部瓶頸混淆。 持續緩慢
隨着負載越來越慢
檢查橋接層和外部系統的版本兼容性。如果有可能,評估不同的橋接供應商。如果重新規劃架構,有可能完全不需要橋接。
內部資源瓶頸:過度使用或分配不足 內部資源(線程、放入池的對象)變得稀缺。是在正確使用的情況下加大負載時出現過度使用還是因爲泄漏? 隨着負載越來越慢
零星的掛起或異常錯誤
分配不足:根據預期的最大負載提高池的最大尺寸。過度使用:請參閱外部系統的過度使用。
不停止的重試 這包括對失敗請求連續的(或者在極端情況下無休止的)重試。 可以預見的鎖定
突然混亂
可能就是後端系統完全宕機。在這裏,可用性監控會有幫助,或者就是把嘗試與成功分開。
線程:阻塞點 線程在過於積極的同步點上備份,造成交通阻塞。 隨着負載越來越慢
零星的掛起或異常錯誤
可以預見的鎖定
突然混亂
可能同步是不必要的(只要重新設計),或者比較外在的鎖定策略(例如,讀/寫鎖)也許會有幫助。
線程:死鎖/活動鎖 最普遍,這是您基本的“獲得順序”的問題。 突然混亂 處理選項包括:主鎖,確定的獲得順序,以及銀行家算法。

2、調優建議

通過分析其配置。我們發現JDBC連接池存在性能問題。

在 WebLogic中就大量使用了池:JDBC Connection Pool、Socket Pool、Object Pool和Thread Pool。I/O操作中,buffer是必須的,特別是對大文件的操作,不然容易造成內存溢出。字節操作最快,所以儘可能採用 write(byte[]),Buffered FileOutputStream比Buffered FileWriter要快,因爲FileWriter需要Unicode到Byte的轉換。JDBC建議使用buffer和cache。爲 HttpServletResponse設置buffersize,使用wl-cache,緩存在JNDI樹上獲取的對象等等。

此外,使用JDK 1.4的非阻塞I/O對性能也有很大提高。

JDBC 代碼調優最大的原則就是使用WebLogic的連接池,而不是自己直連數據庫。在我接觸的很多自己實現連接池的項目中,大部分遇到死鎖和連接泄漏的問題, 最後得不得修改代碼。而WebLogic提供了功能強大,性能良好的數據庫連接池,我們要做的只是封裝一個連接管理類,從JNDI樹上獲取數據源並緩存, 得到連接,並提供一系列關閉數據庫資源的方法。

對任何資源使用的原則是 用完即關,不管是數據庫資源、上下文環境,還是文件。數據庫資源的泄漏極易造成內存泄漏,乃至系統崩潰。在使用完數據庫資源後依次關閉 ResultSet,Statement和Connection,而在一個數據庫連接多次進行數據庫操作時要特別注意ResultSet和 Statement依次關閉。

由於獲取連接時默認自動提交方式,使用 connection.setAutoCommit(false)關閉自動提交,使用PreparedStatement,批量更新,業務複雜或者大數據 量操作時使用存儲過程,儘量使用RowSet,此外設置記錄集讀取緩存FetchSize和設置記錄集讀取方向FetchDirection對性能也有一 定的提高。

Servlet代碼調優比較簡單:在Servlet之間跳轉 時,forward比sendRedirect更有效;設置HttpServletResponse 緩衝區,如:response.setBufferSize(20000);在init()方法裏緩存靜態數據,而在destroy()中釋放它;建議在 Servlet裏使用ServletOutputStream輸出圖片等對象;避免在Servlet和Jsp中定界事務等。

JDBC Connection Pool的調優受制於WebLogic Server線程數的設置和數據庫進程數,遊標的大小。通常我們在一個線程中使用一個連接,所以連接數並不是越多越好,爲避免兩邊的資源消耗,建議設置連 接池的最大值等於或者略小於線程數。同時爲了減少新建連接的開銷,將最小值和最大值設爲一致。增加Statement Cache Size對於大量使用PreparedStatement對象的應用程序很有幫助,WebLogic能夠爲每一個連接緩存這些對象,此值默認爲10。在保 證數據庫遊標大小足夠的前提下,可以根據需要提高Statement Cache Size。比如當你設置連接數爲25,Cache Size爲10時,數據庫可能需要打開25*10=250個遊標。不幸的是,當遇到與PreparedStatement Cache有關的應用程序錯誤時,你需要將Cache Size設置爲0。儘管JDBC Connection Pool提供了很多高級參數,在開發模式下比較有用,但大部分在生產環境下不需調整。這裏建議最好不要設置測試表, 同時Test Reserved Connections和Test Released Connections也無需勾上。 當然如果你的數據庫不穩定,時斷時續,你就可能需要上述的參數打開。

最 後分析一下JDBC驅動程序類型的選擇,Oracle提供thin驅動和oci驅動,從性能上來講,oci驅動強於thin驅動,特別是大數據量的操作。 但在簡單的數據庫操作中,性能相差不大。所以我建議對數據量至少500000條記錄,一般情況5000000條記錄的狀況使用oci驅動。

通過分析其日誌並使用GC資源查看。我們發現存在內存泄露的垃圾回收失敗問題。

垃 圾收集(GC)是指JVM釋放Java堆中不再使用的對象所佔用的內存的過程,而Java堆(Heap)是指Java應用程序對象生存的空間。堆大小決定 了GC的頻度和時間。堆越大,GC頻度低,速度慢。堆越小,GC頻度高,速度快。所以GC和堆大小是一組矛盾。爲了獲取理想的Heap堆大小,需要使用 -verbosegc參數(Sun jdk: -Xloggc:)以打開詳細的GC輸出。分析GC的頻度和時間,結合應用最大負載所需內存情況,得出堆的大小。通常情況下,我們建議使用可用內存(除操 作系統和其他應用程序佔用之外的內存)70-80%,爲避免堆大小調整引起的開銷,設置內存堆的最小值等於最大值即:-Xms=-Xmx。而爲了防止內存 溢出,建議在生產環境堆大小至少爲256M(Platform至少512M),實際環境中512M~1G左右性能最佳,2G以上是不可取的,在調整內存時 可能需要調整核心參數進程的允許最大內存數。對於sun和hp的jvm,永久域太小(默認4M)也可能造成內存溢出,應增加參 -XX:MaxPermSize=128m。建議設置臨時域-Xmn的大小爲-Xmx的1/4~1/3, SurvivorRatio爲8。

爲了獲得更好的性能,建議在啓動文件設置WebLogic爲產品模式,此時sun和hp jvm JIT引擎爲-server,默認情況下打開JIT編譯模式對性能也有幫助。調整Chunk Size和Chunk Pool Size也可能對系統的吞吐量有提高。此外還需關閉顯示GC: -XX:+DisableExplicitGC。

建 議Intel平臺上使用jRockit(使用參數-jrockit)無疑大大提高WebLogic性能。本系統使用SUN JDK1.4.2_08。jRockit支持四種垃圾收集器:分代複製收集器、單空間併發收集器、分代併發收集器和並行收集器。默認狀態 下,JRockit使用分代併發收集器。要改變收集器,可使用-Xgc:,對應四個收集器分其他爲gencopy, singlecom, gencon以及parallel。爲得到更好的響應性能,應該使用併發垃圾回收器:-Xgc:gencon,可使用-Xms和-Xmx設置堆棧的初始大 小和最大值,要設置護理域-Xns爲-Xmx的10%。而如果要得到更好的性能,應該選用並行垃圾回收器:-Xgc: parallel,由於並行垃圾回收器不使用nursery,不必設置-Xns。jRockit 還提供了強大的圖形化監控工具Jrockit Management Console。可以查看GC性能問題。

通過實時查看並分析操作系統與ORACLE系統中的I/O信息。我們發現存在I/O讀寫佔用資源率高且頻繁問題。

WebLogic Server有兩套套接字複用器:Java版和本地庫。採用小型本地庫更有效,儘量激活Enable Native IO(默認),此時UNIX默認使用CPUs+1個線程,Window下爲雙倍CPU。如果系統不能加載本地庫,將會拋出一個異 常:java.lang.UnsatisfiedLinkException,此時只能使用Java套接字複用器,可以調整socket readers 百分比,默認爲33%。該參數可以在Console Server Tuning Configuration配置欄裏設置。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章