【问题标题】:WCF Performance QuestionWCF 性能问题
【发布时间】:2011-05-13 19:41:53
【问题描述】:

我是 WCF 的新手,有一个性能问题。我在客户端执行以下代码:

    try
    {
      for (int i = 0; i < 20; i++)
      {
         stopwatch.Reset();
         stopwatch.Start();

         var psn = client.GetPsnByPsnId(21);
         var psnList = client.GetPsnBySmartBizClientId(2);
         var container = client.GetContainerByContainerId(3);
         var containerList = client.GetContainerBySmartBizClientId(2);

         stopwatch.Stop();
         Console.WriteLine(string.Format("Pass # {0} completed in {1} milliseconds", i + 1,stopwatch.ElapsedMilliseconds));
     }
   }
   catch (FaultException exception)
   {
      MessageBox.Show(string.Format("Error occurred. The error message is {0}", exception.Message));
   }
   finally
   {
      client.Close();
      client = null;
   }

此代码使用 .NET 4.0 下的 HTTP 绑定命中作为 Windows 服务托管的 WCF 服务。我遇到的问题是这个。第一次通过循环,在第一个 WCF 调用 (client.GetPsnByPsnID()) 上,有一个非常显着的延迟,实际上是 10 多秒。但是,在第一次调用之后,每个后续调用,每次通过循环,都需要

有人知道什么可能导致初始延迟吗?

编辑:这是 Windows 服务的 OnStart 代码:

protected override void OnStart(string[] args)
{
   serviceHost = new ServiceHost(typeof(ServiceMethods),new Uri("http://111.111.111.111:1111/Psn"));

   // Add an endpoint and the methods the endpoint will support.
   serviceHost.AddServiceEndpoint(typeof(IServiceMethods), WcfConfiguration.GenerateBinding(Enumerations.WcfBindingType.HTTP), "");

   WcfConfiguration.CreateMexData(serviceHost);
   serviceHost.Open();
}

这里是 GenerateBinding 方法:

public static System.ServiceModel.Channels.Binding GenerateBinding(Enumerations.WcfBindingType bindingType)
{
   System.ServiceModel.Channels.Binding binding = null;

   BasicHttpBinding httpBinding = new BasicHttpBinding();
   httpBinding.Security.Mode = ((bindingType == Enumerations.WcfBindingType.HTTP) ? BasicHttpSecurityMode.None : BasicHttpSecurityMode.Transport);
   httpBinding.OpenTimeout = new TimeSpan(0, 0, 30);
   httpBinding.SendTimeout = new TimeSpan(0, 0, 30);
   httpBinding.ReceiveTimeout = new TimeSpan(0, 0, 30);
   httpBinding.Security.Transport.ClientCredentialType = HttpClientCredentialType.None;
   httpBinding.ReaderQuotas.MaxStringContentLength = httpBinding.ReaderQuotas.MaxStringContentLength;
   httpBinding.MaxReceivedMessageSize = httpBinding.MaxReceivedMessageSize;
   httpBinding.ReaderQuotas.MaxArrayLength = 1048576;
   httpBinding.MaxBufferSize = httpBinding.MaxBufferSize;

   binding = httpBinding;
   break;
   }
   return binding;
}

public static void CreateMexData(ServiceHost host)
{
  ServiceMetadataBehavior behavior = new ServiceMetadataBehavior();

  behavior.HttpGetEnabled = true;
  host.Description.Behaviors.Add(behavior);
  host.AddServiceEndpoint(typeof(IMetadataExchange), MetadataExchangeBindings.CreateMexHttpBinding(), "mex");
}

【问题讨论】:

  • 您的服务和/或 WCF 主机的 OnStart 方法中是否有重要代码?
  • 您的服务是事务性的吗?
  • @mellamokb - 我已经添加了 OnStart 代码。

标签: c# wcf


【解决方案1】:

如果服务在您的测试运行之间没有收到任何命中,它实际上可能正在关闭 WCF 服务应用程序,并且当有新请求进入时,它会完全重新启动应用程序,这也需要更多时间。这可以在 IIS 设置中进行更改(假设您在 IIS 中托管),这样 Worker 进程要么需要更长的时间才能关闭,要么根本不关闭。

此外,WCF 在您的第一次调用中建立 TCP/Http 连接,后续调用可能使用池连接。不必重新建立 TCP/Http 连接可以为您节省大量时间。

最后,在您当前的实施情况下,最好的情况是每次迭代仍然需要执行 4 次服务器往返。 batching your wcf calls together 可能会更好地为您服务,以减少往返次数。

【讨论】:

  • 10 秒? 真的?对于我的 WCF 服务,冷启动和热启动之间的差异分别为 3 秒和 2 秒。
  • @mellamokb:谁知道服务在启动时在做什么?它显然完全依赖于此。我们需要一些代码来确定。
  • @mellamokb 真的。 :) 我有一个 WCF 服务,它的启动时间也很差。似乎与其运行的服务器有关,因为该服务在启动时没有做任何奇怪的事情。
  • @Brook:确实,正如我在对 OP 帖子的评论中提到的那样。在您进行编辑之前,您说从建立第一个 TCP 连接到建立一个池连接需要 10 秒。这就是我所指的,现在无关紧要:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-09
  • 2011-01-07
  • 2012-11-02
  • 2011-07-27
  • 1970-01-01
相关资源
最近更新 更多