性能調優案例

  1. 性能分析案例
    1. 程序分析案例
  1. 用jconse做監控,發現內存持續的不釋放,波谷或者波峯呈現持續上升的趨勢,並且監控tomcat日誌的時候發現有outofmemory:java  heap space的錯誤日誌,就用jmap區定位這個問題,找到了在JVM內存堆中佔用最大的一個類。然後和開發溝通後,對這個方法進行修改後,再次用jconse進行監控,發現內存增長,回收波動變得比較有規律。
  2. 用JDK自帶的jconse做監控,發現JVM線上機器經常出現卡頓現象,JVM在一個小時內會出現一次FULL GC,懷疑是線上JVM老年代,伊甸園區設置不合理,然後看了下配置文件,並把老年代調小,新生代適當的調大。因爲一般對象都是在新生代進行頻繁的創建。這樣設置後儘量讓對象在年輕帶進行回收,儘量進行YOUNG gc,減少FULL GC次數,調整後,發現FULL GC時間間隔明顯增長。對用戶的感知影響也變小。
    1. 中間件分析案例

   用lr做300用戶的併發,在control裏面看到有大量的502,503錯誤,這時候去查看負載機的網絡情況正常,cpu,內存等各項指標均正常,查看數據庫連接數也都正常,並且應用服務和數據庫服務中均沒有錯誤日誌拋出。初步判斷這種情況應該是tomcat沒有接收到這些併發產生的請求,直接將請求摒棄,所以懷疑是不是進程,線程數設置不合理。於是開始查看tomcat配置文件中的進程,線程數,並嘗試將配置文件中的線程數調大,然後再加壓時,發現仍有大量的502,203錯誤,但是比以前稍微少點。那我想是不是進程數太小了,服務器來不及創建進程,就直接把請求摒棄掉了。於是就試着去調初始的進程數,將進程數調大後,再去加壓,發現OK,不再出現502,503錯誤,問題得到解決。

    1. 數據庫分析案例

      測試過程中發現數據庫服務器的CPU佔用經常達到100,於是用show processlist查看mysql的行爲。發現大部分的sql都處於睡眠連接狀態,嚴重消耗mysql服務器的資源。並可能導致mysql的崩潰。於是修改了數據庫配置文件,將wait_timeout(睡眠連接超時時間,如果連接超時,會被mysql自然終止)值適當的調小(由原來的28800改爲600s)。再觀察數據庫服務器CPU稍微降低到90左右,但是還是會很高。那就再用show processlist 查看mysql行爲。發現出現比較頻繁的兩個sql語句爲一個左連接查詢,然後再分別查看了下這個sql語句涉及到的三個表的結構,又發現其中有兩個表只是建了主鍵,並沒有添加索引,然後分別給這兩個表添加索引,並調整了sql語句由左連接改爲普通sql查詢。再反覆的查看數據庫的行爲,又發現了兩個表存在同樣的問題,於是都改爲走索引,然後再觀察數據庫服務器CPU,cpu立刻降了下來,一直在50%~70%之間。

    1. 綜合分析案例

案例一:動態內容爲主的網站。

  • 網站運行環境說明
    • 1臺IBMx3850服務器, 單顆雙核Xeon 3.0G CPU,2G內存,3塊72G SCSI磁盤
    • 操作系統 CentOS 5.4
    • 應用基於LAMP架構,所有服務都在一臺服務器上
  • 性能問題現象以及處理措施
    • 表現:早晨和下午訪問高峯時,服務器頻繁宕機,重啓後的一段時間內能正常服務,過一會以後又變的響應緩慢,然後又宕機。
    • 檢查:發現宕機前系統負載高,內存基本耗盡,Apache httpd.conf 配置最大用戶數爲2000,並且開啓了KeepAlive
    • 處理:修改 httpd.conf 配置文件,降到最大 1500個用戶數,仍然頻繁宕機,又降到 1024個用戶數,系統不宕機了,但是負載很高,站點訪問極慢
  • 初次優化

   既然是系統資源耗盡導致的網站服務失去響應,那麼深入分析系統資源使用情況,通過uptime、vmstat、top、ps等命令聯合使用 

    • 結論:通過uptime命令查看到系統load average值都是在10以上,CPU資源時常耗盡,這是造成響應緩慢或者長時間沒有響應的主要原因,而導致系統資源消耗過道主要是用戶進程消耗資源嚴重。
    • 原因:通過top命令發現apache每個子進程消耗8M內存,正常是1M左右,觀察apache日誌,發現網站首頁訪問頻率最高,網站首頁是個PHP程序,圖片很多,每次用戶訪問都要多次查詢數據庫,查詢數據非常耗CPU,首頁代碼也沒有用緩存機制,導致每個用戶都要重新信息數據庫查詢操作,導致CPU資源耗盡
    • 處理:改寫網站首頁、減少圖片量,對部分頻繁訪問的程序增加cache機制,減少數據庫訪問。
  • 第二次優化

    一段時間後,系統又開始不穩定,訪問高峯時站點無法正常訪問

    • 分析系統資源使用狀況,發現這次是系統內存資源消耗過大,並且有I/O問題。
    • 原因:內存消耗過大,肯上是用戶訪問進程太多導致,上次優化前發現每個apache子進程消耗在8M,如果設置apache最大用戶數爲1024,內存耗盡是比如的,當物理內存耗盡,虛擬內存就會使用,頻繁使用虛擬內存,肯定會造成I/O等待問題
    • 處理:優化代碼,使每個apache子進程佔用的內存保持在1-2M左右,把Apache配置中的 KeepAlive 特性關閉,把apache最大用戶數調成600,這樣apache進程數大量減少,基本保持在500個左右,雖然還是會使用交換內存,但是服務正常了。
  • 第三次優化

    一段時間後,系統又開始不穩定,訪問高峯時站點無法正常訪問

    • 分析發現還是CPU資源耗盡導致的原因。
    • 原因:程序頻繁訪問數據庫,大量的SQL語句中有 where, order by 等子句,且大部分都是複製查詢,需要便利全表,而大量的表沒有建索引,導致MySQL數據庫負荷過高,消耗CPU資源過高。
    • 處理:優化程序中的SQL語句,where和order by子句上的字段建索引,程序增加Cache機制, 
    • 這樣服務基本處於正常狀態,再也沒有出現宕機現象 
  • 網站結構的優化

第3次優化後,網站在程序代碼、操作系統、apache等方面優化的空間越來越小,爲了避免以後出現服務器宕機問題,可以從網站結構進行優化 

    • 增加了一臺專用數據庫服務器,使應用於數據庫分離
    • 若單臺數據庫服務器仍然不滿足性能要求,可以繼續增加一條數據庫服務器,將數據庫進行讀寫分離(主庫負責寫,從庫負責讀),採用主從同步保證數據的一致性,並且採用冗餘切換進行災備 
    • 如果隨着訪問量的增加,前端應用無法滿足性能要求,可以增加多臺web服務器,web服務器之間進行負載均衡部署,解決前端性能瓶頸

案例二:動態,靜態內核結合的網站。

  • 該網站系統結構說明
    • 硬件環境:兩臺IBMx385服務器, 單個雙核Xeon 3.0G CPU,4G內存,3塊73G SCSI磁盤
    • 操作系統 :CentOS 5.4
    • 網站架構:web應用基於I2EE架構的電子商務應用,web端應用服務器是tomcat,採用mysql數據庫,web和數據庫獨立部署在兩臺服務器上 
  • 性能問題現象以及處理措施
    • 表現:訪問高峯,網頁無法打開,重啓java服務後,網站可以正常運行一段時間,過一會後又變得響應緩慢,最後無法打開網頁
    • 檢查:java進程佔用99%的CPU,內存佔用不大,tomcat爲默認配置 
    • 處理:修改 tomcat配置參數,增大最大線程數、超時時間,修改後服務器宕機間隔增長,但是java進行仍然佔用大量CPU
  • 初次優化

   通過netstat、lsof命令發現有大量的java請求等待信息,查看tomcat日誌,發現大量錯誤信息,錯誤信息提示數據庫連接超時,同時訪問網站靜態資源也無法訪問 

    • 結論:tomcat本身是一個java容器,主要用於處理jsp、servlet動態應用,當時處理靜態資源效率很低。主要原因是tomcat無法及時響應客戶端的請求,從而導致請求隊列積壓,導致tomcat徹底崩潰
    • 原因:通過top命令發現apache每個子進程消耗8M內存,正常是1M左右,觀察apache日誌,發現網站首頁訪問頻率最高,網站首頁是個PHP程序,圖片很多,每次用戶訪問都要多次查詢數據庫,查詢數據非常耗CPU,首頁代碼也沒有用緩存機制,導致每個用戶都要重新信息數據庫查詢操作,導致CPU資源耗盡
    • 處理:引入apache,由apache處理靜態資源,tomcat處理動態請求,apache與tomcat之間用Mod_JK模塊進行通信,這樣大幅度提高tomcat應用性能
  • 第2次優化

   經過前面的優化後,在高併發時候,java進程有時還會出現資源上升無法下降的情況 

    • 處理:進行tomcat負載均衡,前端由apache負載用戶請求的調度,後面多個tomcat進行動態的應用解析操作,通過負載均衡,網站性能得到質的提升

案例三:動態內容+cache爲主的網站。

  • 該網站系統結構說明
    • 多臺Web前端服務器, 配置都爲雙核Xeon 3.0G CPU,4G內存,3塊73G SCSI磁盤
    • 操作系統 CentOS 5.3
    • 多臺MySQL數據庫服務器
    • 基於PHP開發的應用 
  • 該應用的特點
    • 大量內容基於數據庫,需要頻繁訪問數據庫,並且數據更新很快
    • 採用頁面cache機制緩解數據庫壓力,但頁面cache只有5分鐘有效期,需要頻繁生成新的cache
    • Cache以文件形式存在磁盤上,都是小文件,最小不到1k,最大不超過128k
  • 問題描述
    • 訪問高峯期時Web前端負載比較高,時常超過10
    • 訪問高峯期時Web前端響應很慢
  • 性能分析
    • 負載比較高,時常會超過10,CPU Idel經常會小於30%,有時Idel爲0,CPU io wait 很大,經常超過30%,磁盤讀每秒不超過100k,磁盤寫每秒1.5M左右,磁盤tps超過100
    • 訪問高峯期時內存也有部分空閒,用於buffer和cache的內存基本佔總內存60%以上,沒有使用交換內存
  • 原因分析
    • 分析該應用的特點後發現,訪問高峯期時,要頻繁生成新的cache文件,或者更新以及過期的cache文件,cache文件目錄爲256x256的哈希結構,因此讀寫文件時磁盤隨機尋址非常頻繁
    • 該應用磁盤寫遠大於磁盤讀的原因是系統cache命中率高,大量文件讀過一次就cache住了,因此讀的開銷很小
    • 寫磁盤的量並不算很大,平均每秒1.5M,但都是隨機寫,因此寫磁盤速度會稍微慢,也因此會消耗大量CPU時間
    • 對比訪問高峯期和訪問量小時候的系統狀態,磁盤寫的tps提高了1倍以上,CPU io wait提高了3倍以上,因此認爲主要性能瓶頸在磁盤寫上
  • 優化辦法
    • 減少磁盤寫的次數,cache文件先寫在內存中,超過一定訪問次數時才寫回磁盤,但由於要修改應用程序,因此執行難度大
    • 減少磁盤隨機寫的次數,前端不使用255x255的哈希目錄,而是把多個cache文件寫在一個大的cache文件中,並且只作追加寫,這樣就能把隨機寫變成了順序寫,cache過期後,整個大的cache文件可以一次刪除。但由於要修改應用,因此執行難度大
    • 上面2個辦法結合使用,聽上去性能會更好,但是執行難度更大
  • 優化辦法
    • 使用tmpfs作cache磁盤(ramdisk也可以),這樣寫都在訪問內存,沒有磁盤IO消耗,缺點是cache的空間不會很大,不能超過2G(該服務器是4G內存),但是不用修改應用程序,執行容易:
      • Mount –bind /dev/shm /var/www/cache
      • 寫一個清cache的腳本程序,配置在cron中,30分鐘執行一次,檢查/dev/shm的使用率超過70%時,使用find命令找出太舊的cache文件刪除掉

    最終採用了這個辦法,高峯期系統負載小於5

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