調優背景
HBCZT信息中心使用IBM X服務器Windows運行其基於JEE技術的應用系統另外運行一個基於COM技術的數據采集應用程序該程序客戶端讀入用戶填寫的xls格式表格文件信息並通過該程序將XLS內容封裝成為XML並打包ZIP後發送到數據采集程序的服務器端服務器端接受到文件後對該ZIP包進行解包並對解包後的XML信息進行解析使用SQL逐條將記錄插入到Oracle數據庫中數據庫連接池已經設置為但批量數據插入數據庫的時候(數據量至少條記錄一般情況條記錄)導致數據庫異常緩慢客戶希望找到系統瓶頸並提出相應性能調優建議
總體思路
硬件調優操作系統調優數據庫調優 略!我們假設都已經是最佳狀態由於本人負責WebLogic部分的調優所以以下思路與內容均為WebLogic方面特此說明
JEE應用架構環境下的系統調優首先我們一般會從應用程序出發去審核代碼做到代碼級的優化然後再調整應用服務器(BEA WebLogic)和數據庫 (Oraclei)的參數最後當然是調整操作系統和網絡的性能(包括硬件升級)這是一種MDA的先進做法誠然在這樣一個政務項目中不可能完全按照這個思路來做我們把目標首先定位在應用系統所在的應用服務器(BEA WebLogic)上通過對BEA WebLogic的參數進行設置使WebLogic能夠在最優化的環境中去運行其系統然後對ORACLE數據的參數進行優化設置最後進行性能測試再找出導致性能瓶頸所在的SQL代碼或JAVA程序考量其修改的可行性並進行最終問題優先級認定與瓶頸模塊進行協商解決性能問題當然一般情況下我見過的案例都是出現了性能問題後才想到調優而且一般都是先進行系統參數調整實在解決不了才會對代碼進行檢查實際上我們應當將代碼級的調優放在應用設計時來做測試生產時修改代碼將是一件極其痛苦的事情
下表為一般性JEE性能調優的參照情況一覽表供參考
毛病
描述
症狀
原因或治法
線性內存洩漏
每單位(每事務
每用戶等)洩漏造成內存隨著時間或負載線性增長
這會隨著時間或負載增長降低系統性能
只有重啟才有可能恢復
隨著時間越來越慢
隨著負載越來越慢
雖然可能有多種外部原因
但最典型的是與資源洩漏有關(例如
每單位數據的鏈表存儲
或者沒有回收的回收/增長緩沖區)
指數方式內存洩漏
雙倍增長策略的洩漏造成系統內存消耗表現為時間的指數曲線
隨著時間越來越慢
隨著負載越來越慢
通常是由於向集合(Vector
HashMap) 中加入永遠不刪除的元素造成的
糟糕的編碼
無限循環
線程在 while(true) 語句以及類似的語句裡阻塞
可以預見的鎖定
您需要對循環進行大刀闊斧的刪剪
資源洩漏
JDBC 語句
CICS 事務網關連接
以及類似的東西被洩漏了
造成對 Java 橋接層和後端系統的影響
隨著時間越來越慢
可以預見的鎖定
突然混亂
通常情況下
這是由於遺漏了 finally 塊
或者更簡單點
就是忘記用 close() 關閉代表外部資源的對象所造成的
外部瓶頸問題
後端或者其他外部系統(如鑒權)越來越慢
同樣減緩了 J
EE 應用服務器和應用程序
持續緩慢
隨著負載越來越慢
咨詢專家(負責的第三方或者系統管理員)
獲取解決外部瓶頸問題的方法
外部系統
J
EE 應用程序通過太大或太多的請求濫用後端系統
持續緩慢
隨著負載越來越慢
清除冗余的工作請求
成批處理相似的工作請求
把大的請求分解成若干個更小的請求
調整工作請求或後端系統(例如
公共查詢關鍵字的索引)等
糟糕的編碼
CPU密集的組件
這是 J
EE 世界中常見的感冒
一些糟糕的代碼或大量代碼之間一次糟糕的交互
就掛起了 CPU
把吞吐速度減慢到爬行的速度
持續緩慢
隨著負載越來越慢
典型的解決方案就是數據高速緩存或者性能計數
中間層問題
實現得很糟糕的橋接層(JDBC 驅動程序
到傳統系統的 CORBA 連接)
由於對數據和請求不斷的排列
解除排列
從而把所有通過它的流量減慢到爬行速度
這個毛病在早期階段很容易與外部瓶頸混淆
持續緩慢
隨著負載越來越慢
檢查橋接層和外部系統的版本兼容性
如果有可能
評估不同的橋接供應商
如果重新規劃架構
有可能完全不需要橋接
內部資源瓶頸
過度使用或分配不足
內部資源(線程
放入池的對象)變得稀缺
是在正確使用的情況下加大負載時出現過度使用還是因為洩漏?
隨著負載越來越慢
零星的掛起或異常錯誤
分配不足
根據預期的最大負載提高池的最大尺寸
過度使用
請參閱外部系統的過度使用
不停止的重試
這包括對失敗請求連續的(或者在極端情況下無休止的)重試
可以預見的鎖定
突然混亂
可能就是後端系統完全宕機
在這裡
可用性監控會有幫助
或者就是把嘗試與成功分開
線程
阻塞點
線程在過於積極的同步點上備份
造成交通阻塞
隨著負載越來越慢
零星的掛起或異常錯誤
可以預見的鎖定
突然混亂
可能同步是不必要的(只要重新設計)
或者比較外在的鎖定策略(例如
讀/寫鎖)也許會有幫助
線程
死鎖/活動鎖
最普遍
這是您基本的
獲得順序
的問題
突然混亂
處理選項包括
主鎖
確定的獲得順序
以及銀行家算法
調優建議
通過分析其配置我們發現JDBC連接池存在性能問題
在WebLogic中就大量使用了池:JDBC Connection PoolSocket PoolObject Pool和Thread PoolI/O操作中buffer是必須的特別是對大文件的操作不然容易造成內存溢出字節操作最快所以盡可能采用write(byte[])Buffered FileOutputStream比Buffered FileWriter要快因為FileWriter需要Unicode到Byte的轉換JDBC建議使用buffer和cache為HttpServletResponse設置buffersize使用wlcache緩存在JNDI樹上獲取的對象等等
此外使用JDK 的非阻塞I/O對性能也有很大提高
JDBC代碼調優最大的原則就是使用WebLogic的連接池而不是自己直連數據庫在我接觸的很多自己實現連接池的項目中大部分遇到死鎖和連接洩漏的問題最後得不得修改代碼而WebLogic提供了功能強大性能良好的數據庫連接池我們要做的只是封裝一個連接管理類從JNDI樹上獲取數據源並緩存得到連接並提供一系列關閉數據庫資源的方法
對任何資源使用的原則是用完即關不管是數據庫資源上下文環境還是文件數據庫資源的洩漏極易造成內存洩漏乃至系統崩潰在使用完數據庫資源後依次關閉ResultSetStatement和Connection而在一個數據庫連接多次進行數據庫操作時要特別注意ResultSet和Statement依次關閉
由於獲取連接時默認自動提交方式使用connectionsetAutoCommit(false)關閉自動提交使用PreparedStatement批量更新業務復雜或者大數據量操作時使用存儲過程盡量使用RowSet此外設置記錄集讀取緩存FetchSize和設置記錄集讀取方向FetchDirection對性能也有一定的提高
Servlet代碼調優比較簡單在Servlet之間跳轉時forward比sendRedirect更有效設置HttpServletResponse 緩沖區如responsesetBufferSize();在init()方法裡緩存靜態數據而在destroy()中釋放它建議在Servlet裡使用ServletOutputStream輸出圖片等對象避免在Servlet和Jsp中定界事務等
JDBC Connection Pool的調優受制於WebLogic Server線程數的設置和數據庫進程數游標的大小通常我們在一個線程中使用一個連接所以連接數並不是越多越好為避免兩邊的資源消耗建議設置連接池的最大值等於或者略小於線程數同時為了減少新建連接的開銷將最小值和最大值設為一致增加Statement Cache Size對於大量使用PreparedStatement對象的應用程序很有幫助WebLogic能夠為每一個連接緩存這些對象此值默認為在保證數據庫游標大小足夠的前提下可以根據需要提高Statement Cache Size比如當你設置連接數為Cache Size為時數據庫可能需要打開*=個游標不幸的是當遇到與PreparedStatement Cache有關的應用程序錯誤時你需要將Cache Size設置為盡管JDBC Connection Pool提供了很多高級參數在開發模式下比較有用但大部分在生產環境下不需調整這裡建議最好不要設置測試表 同時Test Reserved Connections和Test Released Connections也無需勾上 當然如果你的數據庫不穩定時斷時續你就可能需要上述的參數打開
最後分析一下JDBC驅動程序類型的選擇Oracle提供thin驅動和oci驅動從性能上來講oci驅動強於thin驅動特別是大數據量的操作但在簡單的數據庫操作中性能相差不大所以我建議對數據量至少條記錄一般情況條記錄的狀況使用oci驅動
通過分析其日志並使用GC資源查看我們發現存在內存洩露的垃圾回收失敗問題
垃圾收集(GC)是指JVM釋放Java堆中不再使用的對象所占用的內存的過程而Java堆(Heap)是指Java應用程序對象生存的空間堆大小決定了GC的頻度和時間堆越大GC頻度低速度慢堆越小GC頻度高速度快所以GC和堆大小是一組矛盾為了獲取理想的Heap堆大小需要使用verbosegc參數(Sun jdk: Xloggc:)以打開詳細的GC輸出分析GC的頻度和時間結合應用最大負載所需內存情況得出堆的大小通常情況下我們建議使用可用內存(除操作系統和其他應用程序占用之外的內存)%為避免堆大小調整引起的開銷設置內存堆的最小值等於最大值即:Xms=Xmx而為了防止內存溢出建議在生產環境堆大小至少為M(Platform至少M)實際環境中M~G左右性能最佳G以上是不可取的在調整內存時可能需要調整核心參數進程的允許最大內存數對於sun和hp的jvm永久域太小(默認M)也可能造成內存溢出應增加參XX:MaxPermSize=m建議設置臨時域Xmn的大小為Xmx的/~/ SurvivorRatio為
為了獲得更好的性能建議在啟動文件設置WebLogic為產品模式此時sun和hp jvm JIT引擎為server默認情況下打開JIT編譯模式對性能也有幫助調整Chunk Size和Chunk Pool Size也可能對系統的吞吐量有提高此外還需關閉顯示GC: XX:+DisableExplicitGC
建議Intel平台上使用jRockit(使用參數jrockit)無疑大大提高WebLogic性能本系統使用SUN JDK_jRockit支持四種垃圾收集器分代復制收集器單空間並發收集器分代並發收集器和並行收集器默認狀態下JRockit使用分代並發收集器要改變收集器可使用Xgc:對應四個收集器分其他為gencopy singlecom gencon以及parallel為得到更好的響應性能應該使用並發垃圾回收器Xgc:gencon可使用Xms和Xmx設置堆棧的初始大小和最大值要設置護理域Xns為Xmx的%而如果要得到更好的性能應該選用並行垃圾回收器:Xgc: parallel由於並行垃圾回收器不使用nursery不必設置XnsjRockit 還提供了強大的圖形化監控工具Jrockit Management Console可以查看GC性能問題
通過實時查看並分析操作系統與ORACLE系統中的I/O信息我們發現存在I/O讀寫占用資源率高且頻繁問題
WebLogic Server有兩套套接字復用器Java版和本地庫采用小型本地庫更有效盡量激活Enable Native IO(默認)此時UNIX默認使用CPUs+個線程Window下為雙倍CPU如果系統不能加載本地庫將會拋出一個異常javalangUnsatisfiedLinkException此時只能使用Java套接字復用器可以調整socket readers 百分比默認為%該參數可以在Console Server Tuning Configuration配置欄裡設置
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26327.html