Dot-Net

為什麼第一個 WCF 客戶端呼叫很慢?

  • May 4, 2016

我試圖弄清楚為什麼客戶端應用程序啟動後的第一個 WCF 呼叫與第二個相比需要更多的時間。

我做了什麼來測試:

  1. 實現了簡單的自託管 WCF 伺服器和控制台客戶端。
  2. 伺服器已預熱- 我在執行測試之前執行它並多次呼叫方法。
  3. 綁定是basicHttpBinding為了減少網路和安全成本。
  4. 測試場景 - 啟動控制台客戶端應用程序,連續進行兩個相同的 WCF 服務呼叫。

在我的測試中,我看到第一次呼叫約 700 毫秒,第二次呼叫約 3 毫秒。

對於 JIT 編譯器來說,幾乎一秒鐘的時間似乎太多了。如果將這段時間用於初始化一些複雜的基礎架構ObjectContext,例如 Entity Framework,我會接受,但我的程式碼非常簡單並且代理類已經編譯。

我也試過netNamedPipeBinding綁定。結果證明了模式 - 第一次呼叫需要約 800 毫秒,第二次呼叫需要約 8 毫秒。

如果有人能解釋為什麼第一次服務呼叫需要這麼多時間,將不勝感激。

在 Win 7 64 位中測試。

我的實現如下。

契約:

[ServiceContract]
public interface ICounter
{
       [OperationContract]
       int Add(int num);
}

服務實施:

public class CounterService: ICounter
{
       private int _value = 0;

       public int Add(int num)
       {
           _value += num;
           Console.WriteLine("Method Add called with argument {0}. Method  returned {1}", num, _value);
           return _value;
       }
}

伺服器實現:

class Program
{
   static void Main(string[] args)
   {
       Uri baseAddress = new Uri("http://localhost:8080/Service");

       // Create the ServiceHost.
       using (ServiceHost host = new ServiceHost(typeof(CounterService), baseAddress))
       {
           host.Open();

           Console.WriteLine("The service is ready at {0}", baseAddress);
           Console.WriteLine("Press <Enter> to stop the service.");
           Console.ReadLine();

           // Close the ServiceHost.
           host.Close();
       }
   }
}

伺服器配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.serviceModel>
   <services>
     <service name="Server.CounterService">
       <endpoint address="base" binding="basicHttpBinding" name="baseDefault"
         contract="Contract.ICounter" />
       <endpoint address="net.pipe://localhost/Service/netNamedPipe"
         binding="netNamedPipeBinding" name="netNamedPipeDefault" contract="Contract.ICounter" />
       <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
     </service>
   </services>
   <behaviors>
     <serviceBehaviors>
       <behavior name="">
         <serviceMetadata httpGetEnabled="true" />
       </behavior>
     </serviceBehaviors>
   </behaviors>
 </system.serviceModel>
</configuration>

客戶端實現(CounterProxy從服務參考生成):

Stopwatch stopWatch = new Stopwatch();
stopWatch.Start();

using (var proxy = new CounterProxy.CounterClient(_endpointConfigurationName))
{
   output = proxy.Add(1);
}

stopWatch.Stop();
// Get the elapsed time as a TimeSpan value.
TimeSpan ts = stopWatch.Elapsed;

包含該程式碼的函式連續呼叫兩次。

客戶端配置:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
 <system.serviceModel>
   <client>
     <endpoint address="http://localhost:8080/Service/base" binding="basicHttpBinding"
         contract="CounterProxy.ICounter"
         name="baseDefault" />
   </client>
 </system.serviceModel>
</configuration>

通常第一次呼叫會花費更多時間,因為在該呼叫Channel Factory中實例化並準備好進行通信,這會花費時間。創建的Channel Factory將被記憶體並在後續呼叫中重用,因此時間會更少。

<http://social.msdn.microsoft.com/Forums/en/wcf/thread/43f89088-546b-46b0-adf8-214deb1741bd>

如果您呼叫 WCF 服務的頻率低於 15 秒(我們觀察到在我們的應用程序中需要等待大約 20 秒),此 Microsoft 部落格似乎可以解釋您的問題:http: //blogs.msdn.com/b/wenlong /archive/2010/02/11/why-does-wcf-become-slow-after-being-idle-for-15-seconds.aspx

該文章還連結到此條目,其中提到了 SetMinThreads() 的修復,這似乎也是一個促成問題:http: //blogs.msdn.com/b/wenlong/archive/2010/02/11/why-are- wcf-responses-slow-and-setminthreads-does-not-work.aspx

引用自:https://stackoverflow.com/questions/10859832