2009-09-04 79 views
1

我有一箇舊的ASP.NET應用程序。我們發送httpWebRequest到遠程REST服務器並返回XML,大多數情況下應用程序工作正常。最近,我們每天幾次遇到一些高CPU使用率問題。ASP.NET HttpWebRequest停止發送請求,CPU使用率高

在高CPU使用時間期間,我們監視了那些httpWebRequest連接(通過檢查w3wp進程的netstat)。一開始,連接從「ESTABLISHED」變爲「CLOSE_WAIT」狀態,然後在這些連接超時後,這些連接逐一消失,然後再沒有連接。

重新設置IIS之後,當w3wp.exe進程再次啓動時,我們仍然找不到到httpWebRequest目標服務器的任何連接。所以CPU使用率保持在高水平。即使經過多輪重置,它也不會解決問題,直到我們看到一些連接開始連接到httpWebRequest目標服務器時,CPU使用率下降。

我其實認爲這可能是我的代碼沒有正確處理httpWebRequest的問題,我在此處發佈了另一個問題:How to close underlying connections after catch httpwebrequest timeout?

正如在這個問題中提到的,我還發現System.Net.HttpWebRequest.GetResponse()有很多超時異常。當CPU使用率很高時,我們在5分鐘內發現了3500次相同的異常情況。

什麼可能導致這種類型的問題,什麼可能是藥?爲什麼應用程序不再發送請求(因爲netstat中沒有連接)?

這裏是源代碼,以防萬一:

System.Net.HttpWebResponse httpWebResponse = null; 
System.IO.Stream stream = null; 
XmlTextReader xmlTextReader = null; 
try 
{ 
    System.Net.HttpWebRequest httpWebRequest = (System.Net.HttpWebRequest)System.Net.WebRequest.Create(request); 
    httpWebRequest.ReadWriteTimeout = 10000; 
    httpWebRequest.Timeout = 10000; 
    httpWebRequest.KeepAlive = false; 
    httpWebRequest.Method = "GET"; 
    httpWebResponse = (System.Net.HttpWebResponse)httpWebRequest.GetResponse(); 
    stream = httpWebResponse.GetResponseStream(); 
    xmlTextReader = new XmlTextReader(stream); 
    xmlTextReader.Read(); 
    xmlDocument.Load(xmlTextReader); 
    //Document processing code. 
    //... 
} 
catch 
{ 
    //Catch blcok with error handle 
} 
finally 
{ 
    if (xmlTextReader != null) 
     xmlTextReader.Close(); 
    if (httpWebResponse != null) 
     httpWebResponse.Close(); 
    if (stream != null) 
     stream.Close(); 
} 

回答

2

從你的描述,它不我清楚你的高CPU使用率與你的傳出HTTP請求有關。 CPU利用率高可能是由於您的代碼存在錯誤,CLR,IIS或其他錯誤。在不知道哪個組件正在消耗CPU的情況下,您無法進一步做任何事情。

如果我是你,我會首先嚐試將採樣分析器附加到W3WP進程,並查看哪個組件正在使用CPU。這應該指出解決此問題的下一步。

+0

@feroze,非常感謝您的幫助,我沒有任何關於採樣分析器的經驗,請給我一些更多的細節或者我可以學習的一些鏈接。再次感謝。 – machinegone 2009-09-12 21:01:27

+0

您可以從這裏下載CLR分析器:http://www.microsoft.com/downloads/details.aspx?FamilyID=a362781c-3870-43be-8926-862b40aa0cd0&displaylang=en 下面是一些鏈接,顯示如何使用探查: http://msdn.microsoft.com/en-us/library/ms979205.aspx http://msdn.microsoft.com/en-us/magazine/cc300553.aspx 我只是在尋找再次在你的代碼中,引起了我的注意。由於您將XMLTextReader()附加到流中,因此如果文檔非常複雜,解析XML文檔可能會佔用CPU。 – feroze 2009-09-13 20:19:29

+0

@feroze,再次感謝,我會閱讀指南,並在我的服務器上運行它。稍後我會給你更新。謝謝。 – machinegone 2009-09-14 22:13:50

2

我建議你嘗試異步發送請求,以避免阻塞主線程:

using (var client = new WebClient()) 
{ 
    client.OpenReadCompleted += (sender, e) => 
    { 
     using (var reader = XmlReader.Create(e.Result)) 
     { 
      // Process the XML document here 
     } 
    }; 
    client.OpenReadAsync(new Uri("http://www.example.com")); 
} 
+0

Darin,謝謝,我會試試這種方式,看看它是否可以幫助我解決問題。 – machinegone 2009-09-05 07:39:18

2

找到導致問題的代碼的CPU佔用率高的原因可能需要一些時間,因爲您必須找到代碼。我現在正在通過我最近開發的vb.net應用程序開展工作。同時,我開發了一個頁面,其中包含一個管理用戶可以單擊以停止W3WP.exe進程的按鈕。這是一個很好的停止差距措施,直到問題代碼可以被識別和更新。這是我使用的代碼。只需使用一個按鈕在相應的.aspx.vb頁面上調用以下代碼即可創建.aspx頁面。代碼使用命令提示符獲取任務列表並將其寫入文件。然後我解析文本文件以獲取W3WP.exe工作進程的PID。然後,我再次以編程方式訪問命令提示符,以使用PID終止W3WP.exe進程。

Imports System.Web 

Partial Class TAP 
Inherits System.Web.UI.Page 

Protected Sub btnStop_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles btnStop.Click 
    Call thStop_IIS() 
End Sub 

Function thStop_IIS() 

    Dim varRetval As String 
    Dim varPID As String 
dim x as long 
    Dim savePath As String = Request.PhysicalApplicationPath + "exports\" 
    If Dir(savePath + "filename.txt") = "filename.txt" Then 
     Kill(savePath + "filename.txt") 
    End If 

    varRetval = Shell("cmd /c tasklist > " + savePath + "filename.txt") 

    For x = 1 To 90000000 

    Next x 

    varPID = thParse_File_Return_PID(savePath + "filename.txt") 
    varRetval = Shell("cmd /c taskkill /pid " & varPID & " /F") 
    Return True 
End Function 

Function thParse_File_Return_PID(ByVal varFileToParse As String) As Integer 

    On Error GoTo handler_err 

    'Dim FILE_NAME As String = "C:\Users\Owner\Documents\test.txt" 
    Dim FILE_NAME As String = varFileToParse 
    Dim TextLine As String 
    Dim varPID As Integer 
    Dim x As Long 

    If System.IO.File.Exists(FILE_NAME) = True Then 

     Dim objReader As New System.IO.StreamReader(FILE_NAME) 

     Do While objReader.Peek() <> -1 
      'TextLine = TextLine & objReader.ReadLine() & vbNewLine 
      TextLine = objReader.ReadLine() & vbNewLine 
      If InStr(TextLine, "w3wp.exe") Then 
       varPID = Mid(TextLine, 31, 4) 
      End If 
     Loop 

     thParse_File_Return_PID = varPID 

    Else 
     thParse_File_Return_PID = 0 
    End If 



handler_exit: 
    Exit Function 

handler_err: 
    'MsgBox(Err.Number & " " & Err.Description & ":" & "thParse_File_Return_Pages") 
    Resume 

End Function 

End Class