公司網站一直很穩定,前段時間開始偶爾出現網站無法打開,提示504的錯誤,運維有懷疑是程序更新引起的,但是仔細看過代碼並沒有獲取數據量過大的地方,而且數據庫表現也一直很平穩。所以一直也無從下手,不知道問題出在哪里,每一次出現這個問題重啟下iis可以解決,或者有的時候是過段時間自己就解決了,所以這個問題一直懸而未決。
直到昨天晚上網站再次更新,在進行功能驗證的時候頻繁出現這個問題。后來測試出來是一個管理身份的用戶登陸就會引發這個錯誤,並且運維在查看服務器情況的時候發現有大量的http請求,並且狀態為CLOSE_WAIT。看了下請求的ip地址,正是我們的圖片服務器的ip。上網查了下這個問題,發現大都是說這個問題是socket程序中出現的,怎么我們的web程序也出現了這樣的問題呢?
、
先不去糾結這個,還是從代碼入手吧。於是看了下管理身份的用戶登陸的代碼,重要去關注跟圖片服務器相關的地方。最終發現這個賬號登陸后會獲取很多圖片用於在首頁輪轉顯示,關鍵的問題是在顯示這些圖片的時候會先執行一個方法判斷這個圖片路徑是否存在,如果不存在則返回一個默認的本地圖片地址。
public static string GetTrueImgPath(string url) { HttpWebRequest myReq = (HttpWebRequest)WebRequest.Create(url); try { HttpWebResponse myRes = (HttpWebResponse)myReq.GetResponse(); if (myRes.ContentLength > 0) { return url; //存在 } else { return "/Contents/Images/img_fload.gif"; } } catch { return "/Contents/Images/img_fload.gif"; } }
看到這個代碼估計大家一下子就知道問題出在哪里了,HttpWebResponse的請求最后沒有被關閉!所以才會產生那么多CLOSE_WAIT的http連接,正是這些沒有及時關閉的http連接占用了服務器的正常http請求,導致了不能正常訪問。根據我查到的資料,CLOSE_WAIT狀態的連接在2個小時后也會自己關閉的,所以網站才會過段時間自己恢復正常。至此問題的根源已經找到,就差修改代碼然后進行驗證了,代碼修改如下:
public static string GetTrueImgPath(string url) { var myReq = (HttpWebRequest)WebRequest.Create(url); myReq.KeepAlive = false; HttpWebResponse myRes; try { myRes = (HttpWebResponse)myReq.GetResponse(); if (myRes.ContentLength <= 0) { url = "/Contents/Images/img_fload.gif"; } myRes.Close(); } catch { url = "/Contents/Images/img_fload.gif"; } return url; }
更新到服務器后進行驗證也通過了,沒有再出現CLOSE_WAIT的連接,至此問題解決。