2011-12-10 45 views
2

TL; DR版本:WCF服務的行爲(雖然看上去配置HTTP上的最大吞吐量),比一個天真的ASP.NET處理程序實現WCF性能VS簡單的ASP.NET的HttpHandler


慢4倍UPDATE1

切換到發佈模式和IIS(完全不能表達)7.5改變號碼:

  • ASP.NET :從15秒到6.7秒
  • WCF:從60秒到13.7秒

朗解釋:

我一直在尋找一種有效的方式來快速在兩者之間的內部網傳送信息不同的物理機器(命名管道出了問題)。我的通訊合約由以下操作組成:

void SetUserAsState1(int id); 
void SetUserAsState2(int id); 
byte GetUserState(int id); 

很簡單我會說。我不會考慮安全性,可靠性等方面的表現。而通過性能我的意思是可以發送多少個請求/秒給另一臺機器。

我對兩個方案進行測試,我的筆記本電腦:

  • 一個ASP.NET空網站與通用GetData.ashx處理程序可以調用像的http://本地主機:1234 /的GetData ashx的?OP = 1個& ID = 239(IIS Express已經被使用)
  • 在IIS(快遞)與basicHttpBinding的

我怎麼測試中承載的WCF服務?我設置了10個線程,每個線程將向目標發出1000個請求,並測量完成所有10x1000 = 10,000個請求所需的時間。

結果?

  • ASP.NET:15秒
  • WCF:60秒

測試工具:(不,它不是生產質量)

class Program 
{ 
    private static Service1Client _wcfProxy; 

    static void Main() 
    { 
     _wcfProxy = new Service1Client(); 
     _wcfProxy.GetData(); // warm up proxy and service 
     _wcfProxy.GetData(); // make it really warm :P 

     var threads = new Thread[10]; 
     for (var cnt = 0; cnt < 10; cnt++) 
     { 
      //var t = new ThreadStart(TestAspnetHandler); // scenario 1 
      var t = new ThreadStart(TestWcfService); // scenario 2 
      (threads[cnt] = new Thread(t)).Start(); 
     } 
     var sw = Stopwatch.StartNew(); 
     foreach (var thread in threads) 
     { 
      thread.Join(); 
     } 
     sw.Stop(); 
     Console.WriteLine("Done 10 x 1000 calls in " + sw.Elapsed); 
     Console.ReadLine(); 
    } 

    private static void TestAspnetHandler() 
    { 
     var webClient = new WebClient(); 
     for (var i = 0; i < 1000; i++) 
     { 
      webClient.DownloadData("http://localhost:1970/GetData.ashx?id=1"); 
     } 
    } 

    private static void TestWcfService() 
    { 
     for (var i = 0; i < 1000; i++) 
     { 
      _wcfProxy.GetData(); 
     } 
    } 
} 

ASP.NET實現:

public class GetData : IHttpHandler 
{ 
    public void ProcessRequest(HttpContext context) 
    { 
     context.Response.ContentType = "text/plain"; 
     var id = context.Request.QueryString["id"]; 
     if (string.IsNullOrEmpty(id)) 
     { 
      context.Response.Write("Hello World"); 
     } 
     else 
     { 
      var identifier = int.Parse(id); 
      context.Response.Write(identifier * 23); 
     } 
    } 

    public bool IsReusable { get { return true; } } 
} 

默認4。0配置,沒有改變


WCF合同:

[ServiceContract] 
public interface IService1 
{ 
    [OperationContract] 
    int GetData(); 
} 

和實施

[ServiceBehavior(
    ConcurrencyMode = ConcurrencyMode.Multiple, 
    InstanceContextMode = InstanceContextMode.Single)] 
public class Service1 : IService1 
{ 
    public int GetData() 
    { 
     return 23; 
    } 
} 

和配置:

<services> 
    <service behaviorConfiguration="beh" name="IService1"> 
    <endpoint address="" binding="basicHttpBinding" bindingConfiguration="basicHttp" 
       contract="WcfService1.IService1" /> 
    </service> 
</services> 

<bindings> 
    <basicHttpBinding> 
    <binding name="basicHttp" allowCookies="false" /> 
    </basicHttpBinding> 
</bindings> 

<behaviors> 
    <serviceBehaviors> 
    <behavior name="beh"> 
     <serviceThrottling maxConcurrentCalls="1000" maxConcurrentInstances="1000" maxConcurrentSessions="1000" /> 
     <serviceMetadata httpGetEnabled="true"/> 
     <serviceDebug includeExceptionDetailInFaults="false"/> 
    </behavior> 
    </serviceBehaviors> 
</behaviors> 
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" /> 


我設置的併發性模式到多(所以他們不sync'ed),單一的服務實例,限制設置爲高值,說不上如果/我怎樣才能加快了WCF服務。 WCF服務會追趕ASP.NET的一個變化(通過HTTP實現)嗎?

回答

1

Tcp無法解決問題? 您可以從序列化中獲得更多性能 - 請嘗試NetDataContractSerialization或protobuf.net。您可以緩存通道工廠 - 因此不需要添加服務引用。

+0

不,NetTcpBinding不會出問題。我有一些頭痛的設置,我暫時發送到pzd_ms。加上basicHttpBinding提供了一個更加與ASP.NET的比較。 –

+0

如果所有其他選項用完,我會嘗試TCP :) –

+0

還有一個我在服務器上忘記的設置 - 與啓用gc相關的設置。在生產環境中,使用異步WCF,默認序列化,使用netTcp並且沒有安全性(是的,生產,沒有給出shhhh的名字)我在客戶機和服務器之間往返40-50毫秒。由於netTcp激活,第一個請求持續了一段時間,但之後它變得輕而易舉。 – DaeMoohn