前面一篇文章中我已經對項目的基本情況進行了簡單的介紹,今天就開始動手針對系統進行效能調優。在效能調優上面說實話我算是個菜鳥,並沒有太多的經驗和紮實的基礎,所以有錯誤的地方希望大家指出。
對於一個BS的系統來說,總共涉及到3個角色:Web伺服器、資料庫伺服器和用戶端。效能調優的第一步也是最重要的一步就是尋找瓶頸。到底是Web伺服器中的程式有問題還是資料庫伺服器上的SQL查詢語句有問題,或者是用戶端上的HTML、JS、Flash、SilverLight、圖片有問題?就算知道了是哪個角色出現了問題,那麼到底是CPU上的問題、記憶體問題、磁碟IO問題還是網路問題?如果沒有找到瓶頸就開始調優,那無異於緣木求魚。舉個簡單的例子,如果一個頁面用戶端請求要10秒鐘系統才響應,在網路傳輸和瀏覽器展現上用了1秒,Web伺服器進行邏輯處理和運算用了8秒,SQL伺服器進行資料查詢用了1秒,如果錯誤的將瓶頸判斷為SQL伺服器,對SQL查詢進行調優,廢了九牛二虎之力將查詢效率提高了100倍(只需要0.01秒),單從SQL調優上來說算是比較成功的,但是從整體而已,用戶端請求該調優後的頁面還是要花9.01秒,使用者可能根本感覺不到10秒和9.01秒的差別,所以整個調優是失敗的。
前面說到BS系統中的3個角色:Web伺服器、資料庫伺服器和用戶端。要尋找瓶頸在哪個角色上,最好的情況是這3個角色是3台不同的電腦,而且這3台電腦最好比較單純,也就是說Web伺服器上就只跑了一個IIS,其他什麼服務都不跑,SQL伺服器上只運行了SQL Server,用戶端只運行了個IE,而且IE只開啟了我們要調優的這個系統。一般來說,大多數瓶頸都是出現在WEB伺服器或SQL伺服器上,很少有在用戶端出現瓶頸的。(不過我還真遇到過用戶端出現效能瓶頸的情況,由於使用了一個不正確的GIF圖片,該圖片導致用戶端CPU佔用100%,使得使用者感覺系統響應很慢。)
首先確認瓶頸是否在用戶端。調查使用者在使用該BS系統時的硬體和軟體環境,是不是只有配置低的電腦才感覺系統緩慢?是不是只有使用了FireFox的使用者才感覺系統緩慢?使用者在使用該系統時是不是CPU佔用過高?通過對用戶端的一些調查就可以確定瓶頸是否在用戶端了。真是在用戶端的話那就要最佳化JS、最佳化HTML等。
確認了瓶頸沒有在用戶端,那麼剩下的就是2台伺服器。要確定到底是哪台伺服器的問題,用到的主要工具就是Windows計數器。在使用Windows計數器之前還可以使用Windows的工作管理員來大概的查看一下CPU、記憶體、進程的使用方式。但是切不可看到資料庫伺服器的CPU高就說是資料庫伺服器的問題,也可能是WEB伺服器上啟動並執行程式有問題。我以前就遇到過這樣的情況,即使是在業務低穀期(下班後,晚上時間)資料庫的CPU佔用率一直居高不下,經過好長時間的分析,終於找到原因,原來是程式裡面寫了死迴圈,在不斷的執行資料庫操作。另外,就算能夠確定是資料庫的問題,也不能因為CPU佔用高就認為是執行的運算太複雜,其實更大的可能是因為對資料的IO太多。大量的IO操作可能造成CPU負擔加重。
在Windows計數器中可以監視系統的記憶體、CPU、磁碟還有各應用程式自身提供的計數器(SQL Server、Asp.Net等都有自身的計數器)。要監視系統的記憶體情況可以添加Memory下的Pages/sec ,這個計數器表示實體記憶體和硬碟上的虛擬記憶體的分頁互動情況,數值越大,表示系統讀寫虛擬記憶體頻繁,主機繁忙,平均值一般在20以下最好。另外還有大量的ASP.NET和SQL Server的計數器,我就不一一介紹了。
如果環境允許,我們將業務系統轉移到測試環境中,而且是將Web伺服器和SQL伺服器分開,同時如果能夠讓測試環境和生產環境的硬體設定和網路設定這些都差不多那就更好了。使用LoadRunner或者是VS或者其他壓力測試工具類比多個使用者對效能有問題的頁面進行壓力測試,同時開啟伺服器上的相關計數器。通過對兩個伺服器的監控,基本上就可以判斷出到底哪個伺服器存在效能瓶頸。
如果要獲得更詳細的效能瓶頸資訊,那麼需要獲得程式的原始碼,然後修改原始碼在其中加入記錄時間的代碼,在頁面初始化的時候、調用資料庫之前、調用資料庫之後、頁面Render完成之後分別加入記錄時間的代碼,將這些時間記錄下來,然後可以得到頁面載入的時間,調用資料庫花費的時間。比如頁面載入花了10秒鐘,從時間記錄上看,調用資料庫花了9秒鐘,那麼說明效能的瓶頸是在資料庫上,而不是在Web伺服器上。
另外還有一種辦法可以獲得函數調用的時間,那就是使用.net效能跟蹤的工具ANTS Profiler,這個工具是Red Gate公司出品的一款工具,十分好用,在我以前的部落格中也進行了介紹。使用這個工具Host到Web伺服器的IIS上,然後開啟IE瀏覽器我們就做業務操作,該工具就可以跟蹤出開啟某個頁面,做某些頁面操作的時候調用每個函數的時間,同時也列出了哪些函數調用比較費時。在開啟ANTS Profiler進行.net效能跟蹤的同時,SQL Server上也應該開啟SQL Server Profiler對資料庫進行跟蹤。比如在頁面上我們執行的一個查詢,系統返回了查詢的表格,通過ANTS Profiler跟蹤得到查詢操作耗時9.2秒,而我們在SQL Server Profiler中看到查詢資料庫耗時(Duration欄位)8921ms,整個操作是9.2秒,資料庫操作就花了8.9秒,顯然瓶頸是在資料庫上。