第189期 / July 5, 2013

研發新視界

分享到臉書!分享到維特!分享到噗浪!分享到Google+!分享到微博!轉寄友人友善列印

IIS-Based系統架構於COM+元件發生Memory Leak的調教經驗分享

作者/蘇福泰

[發表日期:2013/7/5]

前言

隨著雲端時代的來臨,網際網路已經深入發展成為人們生活的一部分,所以利用Web建構一套完整的雲端服務系統成為目前許多開發者的第一選擇,透過Web建構的系統不論在個人電腦,甚至是非常熱門的智慧型手機與平板電腦,只要透過內建或自行安裝的瀏覽器就可以使系統較簡易達成支援跨平台裝置來滿足廣大使用者的需要,減少系統整體開發的成本與時程。然而上線於網際網路除了大幅降低使用門檻,也意味著將帶來龐大的使用量,因此系統在面對如此龐大使用者的流量壓力時,系統發生Memory Leak的風險也會相對提高。當發生Memory Leak時不但會引發系統產生非預期性的錯誤,甚至造成整個系統的停擺。因此針對Memory Leak的問題,本文將分享實際實施在IIS-Based架構於COM+元件的上線系統調教經驗,透過Debugger工具與Log記錄分析找尋問題癥結點,最後改善不必要的資源呼叫與過於龐大Transaction的問題來降低系統發生Memory Leak的次數。冀望本文的經驗分享可以指引之後的開發者與維護者在面對Memory Leak問題上有一個正確的思考方向,以利在開發階段或維護階段都能兼顧系統穩定性,降低上線後維護系統的人力負擔與時間成本。

何謂Memory Leak

本文簡單針對Memory Leak定義為應用程式在分配某段記憶體後,由於在釋放記憶體前就失去對內部記憶體的控制,造成內部記憶體的浪費。簡單舉例而言,假設您買了一件新西裝放入衣櫥,突然您遺忘這件西裝的存在,之後為了開會需要又買了一件同樣款式的新西裝放入衣櫥,如果您遺忘的現象持續發生,則這個衣櫥將會被一堆不必要的西裝給塞滿。接下來本文將透過實際上線的IIS-Based系統為例,針對Memory Leak發生的原因作進一步說明。如下簡單系統架構圖,此上線系統是架構於IIS內並以Visaul Basic 6開發的COM+元件為主要商業邏輯核心,並統一透過DB Helper COM+元件作為資料庫的溝通窗口,所以當COM+ Object A正與DB Helper進行長時間Transaction的當下,COM+ Object B也想要進入操作Transaction動作時,由於COM+ Object A已將DB Helper的Transaction Lock住,所以COM+ Object B強迫進入等待的狀態,可是當COM+ Object A的Transaction過程中有未預期的意外發生,如:消耗完可用的記憶體配置,而觸發COM+元件保護系統機制來強迫中斷DB Helper上所有的Transaction,因此COM+ Object B就會遲遲無法等到DB Helper的回應來完成正常工作後的釋放,這情形就是一個典型Memory Leak問題的產生。


《圖一》


找尋問題瓶頸點

當系統維護者面對系統發生Memory Leak的問題時,因為整個龐大的系統中不知道真正發生問題的瓶頸點而有類似海底撈針的困擾,所以事先利用好的工具與方法就是預防與解決Memory Leak的最好措施,因此以下分享一些如何找尋問題點的工具與方法。

一、瀏覽器的Debugger工具

由於現代瀏覽器的激烈競爭使得瀏覽器越來越進步,目前在IE、Chrome與Firefox都會內建或可擴充Debugger工具來幫助開發者縮短開發時間,而Debugger工具除了可以用來補助開發外,也能幫助追蹤頁面執行的資訊,下圖為執行一個子系統的所有過程時間,可以看出其中一項動作的花費時間比其他動作不正常的多出許多,因為Memory Leak通常會伴隨有長時間Transaction的作業而發生,所以透過點選瀏覽詳細資訊就可以針對這隻不正常耗費時間的程式進行分析與調教來協助判斷是否為問題癥結點。


《圖二》


二、Error Log

當開發一個上線系統應為預防未預期的錯誤行為進行適當處理並記錄下Error Log,以這個已上線系統為例,因為已建構完整的錯誤處理機制,因此在找尋Memory Leak就能正確提供系統維護者相關資訊以利後續尋找問題的處理,下圖為將發生Memory Leak的記錄以時間軸的方式呈現。


《圖三》


三、IIS Log

當系統是選擇架設於IIS系統時,只要頁面有任何Transaction的發生,IIS會根據當時狀況將所有Transaction留下記錄。而這個IIS Log配合Error Log就會相當的好用,以上圖Error Log為例,因為6月5日這天發生Memory Leak的狀況集中在19點之後,所以就可以根據這個線索去追溯IIS Log於19點前是否有其他程式在進行過長時間的Transaction而可能導致Memory Leak的發生。追溯情況如下圖,透過IIS Log可以清楚發現在18:58與19:02的兩個時間點正在發生超過12秒的較長時間Transaction,之後系統維護者就可以透過這個線索去作進一步的程式分析。


《圖四》


四、Trace Log

為了再進一步縮小問題範圍可以針對特定範圍的程式主動進行Trace Log的方式,直接針對程式增加記錄Log程式區間,以便將Runtime時最真實的執行狀況記錄下來,以利後續找尋最接近問題點的作業區段,下圖為做完Trace Log後的記錄,可以發現有個作業區段有過長的Transaction發生。


《圖五》


分析與降低Memory Leak的風險

透過上述介紹的工具與方法縮小整體系統的問題發生範圍後,接下來就可以針對這個範圍作詳細的系統分析。以此上線系統為例,除了基本檢測物件變數是否在使用完後有正常設為Null或Nothing來釋放資源外,經過Code Review分析與實驗後發現有2個問題癥結點會造成系統產生Memory Leak的情形。

一、不必要方法的呼叫

以這次案例中,使用者登入必定會執行到的程式中有一個區段會不必要地呼叫Java Web Service做物件初始化的動作,雖然在單一執行或測試這隻程式時並不會發現任何不妥的狀況,然而此程式在使用者登入時至少會執行一次,所以造成此程式區段被非常頻繁的進行呼叫與物件初始化動作,最後會造成整個系統產生過多記憶體的不必要消耗而發生Memory Leak。經過移除不必要的程式區段後情況獲得了有效的改善,此程式發生Memory Leak的次數由原本2個禮拜會發生29次降低至0次。


《圖六》


二、過於龐大的Transaction資料量

以這次上線系統的案例中幾乎大部分的程式都是因為這個問題造成過度消耗大量記憶體而造成Memory Leak。以下圖為例,透過之前介紹過的Trace Log方式後發現有個程式區段會執行過長的時間。


《圖七》


因此針對這個區段進行資料Transaction模擬後發現交易資料量過於龐大,因此會造成記憶體大量的消耗,經過程式建議優化後資料量大小減少了99.9%,交易時間也減少了約85.7%。


《圖八》


以上述優化方法的逐步應用到程式上,在實際監控改善前後在系統錯誤的發生率上,以對半遞減的統計數字呈現在實績上。


《圖九》


總結

本文針對IIS-Based系統架構於COM+元件發生的Memory Leak問題,透過Debugger工具與Log記錄分析找尋問題的癥結點,最後透過改善不必要的資源呼叫與過於龐大的Transaction資料量來降低Memory Leak的出現次數,實際於上線系統實施後的確有效地大幅降低這些改善後的程式發生Memory Leak的次數。而本文分析歷程也可以發現,Memory Leak的發生會和過長時間的Transaction與異常消耗大量記憶體的現象有所關連,這個問題在開發階段進行單一執行與分析時較不易發現異狀,直到上線面對龐大網際網路使用者壓力或系統開始大幅成長時,各個容易消耗記憶體的作業開始競爭記憶體資源,而產生排擠效應,因此Memory Leak的問題就會漸漸浮現。所以當開發者在進行系統時開發時除了必須謹慎評估呼叫資源後的退場機制外,也要顧慮Transaction資料量的大小,以降低作業之間的排擠效應與Memory Leak的發生機率。以本文改善作業為例,系統某ASP程式在執行查詢作業時會透過COM+撈取過多不必要的TABLE欄位,雖然整體的資料筆數不多,可是其中的欄位記錄著大量文字內容已經造成Transaction的資料量過於龐大,但是從COM+得到的龐大Recordset又不能完全吻合ASP端實際的程式需求,使得必須利用額外的ASP程式再次搜尋此龐大的Recordset造成系統資源的浪費,不僅提高產生排擠效應的機會也成為日後系統維運的不穩定因子。所以若能在系統分析階段做好完善的系統防禦考量,如:空白搜尋條件的防呆、系統發生Out of memory的主動通知機制;或者在系統設計階段考量健全的商業邏輯,如:合理的資料查詢筆數限制、呼叫資源後的退場機制等方法都能預防與降低系統發生Memory Leak的機率。所以在預防與解決Memory Leak問題上,開發者與維護者是相輔相成的關係,開發者提供良善維護機制給維護者,維護者回饋問題癥結點給開發者,在此良性循環下,不僅能提高系統的穩定度,也能降低上線後維護系統的人力負擔與時間成本。

參考資料

1.http://msdn.microsoft.com/en-us/library/windows/desktop/ms685978(v=vs.85).aspx
2.http://en.wikipedia.org/wiki/Memory_leak
3.http://www.dotblogs.com.tw/rainmaker/archive/2009/11/04/11405.aspx