《Windows 用戶態程序高效排錯》市場價:35元 特價:29.8元 購買>>
1.3 簡單的問題最棘手:稀疏平常的ASP.NET Session Lost問題
1.3.1 問題描述
客戶抱怨,剛剛開發完成的大型ASP.NET站點測試階段一切正常,但是放到生產環境上,運行壓力一大,就會發生Session Lost現象。問題的表現是一個NullReferenceException異常。分析代碼后發現,該NullReferenceException是試圖訪問一個SessionObject時候發生的。該SessionObject應該在前面就已經設置過。問題半年來一共就發生過3次,而且是在3個不同的頁面發生。
1.3.2 制定策略
這個問題困難的地方在于重現的幾率很小,沒有多少詳細觀察的機會。所以,必須制訂非常周全的計劃,以便問題再次發生的時候,獲取足夠多的信息。如何制訂周密的計劃呢?
思路非常直觀,了解Session實現的細節,總結出導致問題的所有可能性,獲取信息的時候排查所有的可能性。
關于ASP.NET Session的細節,可以參考:
Underpinnings of the Session State Implementation in ASP.NET
有了對Session的理解后,把這個問題分成了下面幾種情況:
1.客戶使用了負載均衡的環境,但是沒有正確配置基于數據庫或者服務的Session模式?;蛘呤菐着_服務器的Machine key沒有配置成一致。跟客戶確認后排除了這種情況,因為客戶只有一個服務器,使用的In-Proc。
2. 最簡單的情況就是所有的用戶,所有的session都丟了。這種情況一般發生在In-Proc的session mode上。原因就是appdomain重啟或者IIS進程崩潰??梢酝ㄟ^性能日志或系統日志來排查。
3. 稍微麻煩一點的就是某一個用戶的session丟了,而沒有影響到所有用戶。觀察方法是,首先在session start里面做log,把每一個session的創建時間以及session id都記錄到本地的一個log里面,同時往session里面添加一個測試用的session value。問題發生的時候,在ASP.NET的全局錯誤處理函數中當前的session id讀出來,比較log中的記錄看看這個session是不是剛剛建立的。如果是,很有可能是客戶端的原因導致session id丟了,比如IE crash導致cookie丟失。
4. 如果不是,那就看看測試用的session value是不是丟了。如果這個也丟了,應該是代碼中掉了Session.Clear。
5. 如果測試用的session value沒有丟,情況就變成一個用戶的session里面的一部分value丟了。很可能是由于用戶的代碼邏輯導致的。解決方法就是通過更詳細的log來定位問題,然后閱讀代碼來檢查。
可以看到,問題的特征跟潛在的根源是對應的。目的在于區分出這3種情況:
1.所有用戶的所有Session全沒有了。
2. 一個用戶的Session沒有了。
3. 一個用戶的部分Session沒有了。
針對每種情況,采取的log策略是:
對于第1類情況,可以在Application_Start/End函數中記錄下時間來檢查Appdomain是不是重新啟動過。
對于第2類情況,log文件應該記錄下session id和session創建的時間。以便判斷問題是否是cookie id lost導致的。如果是cookie id lost,那問題就出在客戶端,或者是網絡原因。
對于第3類情況,可以在工程中搜索所有Session Clear的調用,每次調用前寫log文件來記錄。如果工程很大,無法逐一添加,可以加載調試器,在Session Clear函數中設定條件斷點來記錄。
1.3.3 具體操作和結論
總結下來,具體的實現是:
1. 在global.asax文件的session_start中把這個session的創建時間記錄到session里面。這個創建時間也同時充當測試用的session value。
2. 代碼中對session操作的地方,寫log到以sessionid為文件名的文件中去。
3. 用log文件記錄每次session的操作,發生在什么函數,發生的時間,session內容的變化。
4. 當Exception發生的時候,在Exception handler中記錄發生問題的session id和殘留下來的Session value。
這樣,問題發生的時候,根據Exception handler記錄的session id找到log文件,就可以很清楚地得到所需要的信息。
在做了上述部署之后,等了大約一個星期問題重現了。在log文件中,發現這樣的信息:
1. 某一個用戶的部分Session丟失。
2. 從Session創建時間看,該Session已經維持很長時間了。
3. 通過檢查Session Clear的調用紀錄,發現丟失的Session的確是由用戶自己的代碼清除的。同時發現這些代碼的運行次序跟設計不吻合。根據設計初衷,在清除 Session后,頁面會重定向到一個專門的頁面并重新添加Session,然后繼續操作。但是log表明這個專門的頁面并沒有得到執行。
原文轉自:http://www.anti-gravitydesign.com