16

我试图弄清楚为什么客户端应用程序启动后的第一个 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>
4

4 回答 4

8

通常第一次调用会花费更多时间,因为在该调用Channel Factory中实例化并准备好进行通信,这会花费时间。创建的Channel Factory将被缓存并在后续调用中重用,因此时间会更少。

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

于 2012-06-02T05:03:19.550 回答
3

如果您调用 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

于 2015-06-15T03:39:23.317 回答
2

我有类似的问题。所以我们实际上做了什么,我们编写了每隔一段时间调用 WCF 服务的服务。我知道这不是一个优雅的解决方案,但它正在工作。

于 2012-06-02T04:43:20.807 回答
2

当我第一次创建我的服务代理实例时,我看到了 30 秒范围内的延迟,我知道这一定与某种网络超时有关。

最后对我来说,它实际上是检查被公司代理(是的 Websense)阻止或挫败的证书吊销列表,如下所示:WCF 服务启动太慢?您是否考虑过 CRL 检查?.

为了将来参考,如果链接失效,它归结为将以下内容添加到客户端配置中:

<configuration>
  <runtime>
    <generatePublisherEvidence enabled=“false”/>
  </runtime>
</configuration>
于 2016-05-04T09:27:47.743 回答