2011-06-30 45 views
6

我有一個使用20周左右的螺紋連接到遠程Web服務器併發送任意HTTP請求的大小相當小,通過SSL 100%的控制檯應用程序做一個C#應用程序。遠程Web服務器實際上是一個完整的負載均衡數據中心,其中包含高可用性系統,每秒可處理數十萬個請求。這不是服務器或帶寬問題。說到這裏,我不會運行它,也不會對它的配置有任何影響,所以即使我願意,我也無法進行服務器端更改。如何使用HttpWebRequest的行爲很像提琴手

當使用fiddler運行應用程序時,應用程序執行得非常快。當不在小提琴手中運行時,它真的非常慢,從而無法完成手頭的任務。它似乎也在這個過程的早期鎖定在某個時刻,但這可能只是一個僵局問題,我還不確定。

總之,小提琴手是一個代理,無疑是改變我的請求/以某種方式確保精彩吞吐量連接,但是我不知道它在做。我想弄明白,這樣我可以強迫我的.NET應用程序模仿小提琴手連接處理行爲而實際上不必通過提琴手

我已經粘貼了以下連接代碼來運行它。

 using System; 
    using System.Collections.Generic; 
    using System.Linq; 
    using System.Text; 
    using System.Net; 
    using System.IO; 

    namespace Redacted 
    { 
     public class HiveCommunicator 
     { 

      public static IResponse SendRequest(IRequest request) { 

       ServicePointManager.DefaultConnectionLimit = 60; 
       ServicePointManager.Expect100Continue = false; 


       string hostUrlString = string.Empty; 
       if (request.SiteID <= 0) 
       hostUrlString = string.Format("{0}://{1}{2}", request.UseSSL ? "https" : "http", DataCenters.GetCenter(request.DataCenter), request.Path); 
       else 
       hostUrlString = string.Format("{0}://{1}{2}", request.UseSSL ? "https" : "http", DataCenters.GetCenter(request.DataCenter), string.Format(request.Path, request.SiteID)); 

       HttpWebRequest webRequest = (HttpWebRequest)HttpWebRequest.Create(hostUrlString); 

       switch (request.ContentType) 
       { 
       default: 
       case ContentTypes.XML: 
        webRequest.ContentType = "application/xml"; 
        break; 
       case ContentTypes.JSON: 
        webRequest.ContentType = "application/json"; 
        break; 
       case ContentTypes.BINARY: 
        webRequest.ContentType = "application/octet-stream"; 
        break; 
       } 

       if (request.RequiresAuthorizationToken) 
       { 
       AuthorizationToken tok = HiveAuthentication.GetToken(request.SiteID); 
       if (tok == null) 
       { 
        return null; 
       } 
       webRequest.Headers.Add(HttpRequestHeader.Authorization, tok.Token); 
       } 

       bool UsesRequestBody = true; 

       switch (request.HttpVerb) 
       { 
       case HttpVerbs.POST: 
        webRequest.Method = "POST"; 
        break; 
       case HttpVerbs.DELETE: 
        webRequest.Method = "DELETE"; 
        UsesRequestBody = false; 
        break; 
       case HttpVerbs.PUT: 
        webRequest.Method = "PUT"; 
        break; 
       default: 
       case HttpVerbs.GET: 
        webRequest.Method = "GET"; 
        UsesRequestBody = false; 
        break; 
       } 

       HttpWebResponse webResponse = null; 
       Stream webRequestStream = null; 

       byte[] webRequestBytes = null; 
       if (UsesRequestBody) 
       { 
       webRequestBytes = request.RequestBytes; 
       webRequest.ContentLength = webRequestBytes.Length; 
       webRequestStream = webRequest.GetRequestStream(); 
       for (int i = 0; i < webRequest.ContentLength; i++) 
       { 
        webRequestStream.WriteByte(webRequestBytes[i]); 
       } 
       } 

       try 
       { 
       webResponse = (HttpWebResponse)webRequest.GetResponse(); 
       } 
       catch (WebException ex) 
       { 

       webResponse = (HttpWebResponse)ex.Response; 
       } 

       if (UsesRequestBody) 
       { 
       webRequestStream.Close(); 
       webRequestStream.Dispose(); 
       } 

       IResponse respReturn = request.ParseResponse(webResponse); 
       webResponse.Close(); 

       return respReturn; 
      } 
     } 
    } 

回答

5

我感謝在這裏試圖幫助的人們。不幸的是,這需要致電Microsoft Profesional Support。

儘管我使用的是ServicePointManager.Expect100Continue = false;它發生在應用程序生命週期的最後階段。查看System.Net.Trace日誌,我們看到expect-100 continue頭仍在使用中(除了使用fiddler時)。解決的辦法是把這個到應用程序啓動(在main())

我還試圖關閉請求流之前讀取響應流。

修復後,一切都很好地加快。該應用程序運行得更快,沒有小提琴手比,這是我所期望的。

一對夫婦說要在HttpWebResponse上調用dispose。該類沒有公共的Dispose方法。我假設.Close()調用.Dispose()內部雖然。

+1

我也遇到了這個頭的問題。我無法理解MS爲何如此難以改變。 –

1

瞎猜在這裏,但它可能有一個簡單的app.config設置做:

<system.net> 
    <connectionManagement> 
    <add address="*" maxconnection="40"/> 
    </connectionManagement> 
</system.net> 

我曾在一個多線程HTTP同樣的問題,請求應用程序,一旦這種解決那個問題。

+0

謝謝你的提示,我已經試過了,它似乎並沒有工作,但感謝您的建議;) – Erick

+0

感謝的Mikael。這個對我有用! – carck3r

2

可以玩弄提琴手的「連接選項」,查看是否有小提琴手的強大吞吐量的原因是重複使用的客戶端連接。如果是這樣的話,你可能要考慮實現一個共享的安全http連接池,或者只是看電影或其他東西。 ^^

+0

林不知道該去哪裏瞭解有關設置「共享安全http連接池」的信息我想知道你是否可以建議一些谷歌搜索術語 – Erick

+2

(http://stackoverflow.com/questions/4933450/can-i -reuse-httpwebrequest-without-disconnected-from-the-server)Jon Skeet建議在WebResponse上顯式調用dispose,以便底層基礎架構可以重用相同的連接。也許這會有所幫助。 –

+0

賓果。喬恩的答案几乎肯定是正確的。 – EricLaw

0

鑑於您的應用程序發送「任意HTTP請求尺寸相當小」,它可以幫助禁用Nagle算法。

ServicePointManager.UseNagleAlgorithm = true; 

MSDN:一些元件的可使用時HttpWebRequest的,包括影響性能:

Nagle算法[...]通過網絡發送數據之前累積小消息的序列成較大的TCP數據包。一般來說,對於恆定的高容量吞吐量,使用Nagle算法可以提高性能。但對於較小的吞吐量應用,可能會看到性能下降。 如果應用程序使用低延遲連接,則可能有助於將此屬性設置爲false。