WCF C#本地托管服务的性能降低

时间:2015-11-17 07:18:52

标签: c# performance wcf

我创建了一个WCF服务;一个简单的getData(i)。我在一个Windows服务中托管它;写了一个客户端来访问该服务。 getData(i)是“空” - 它只返回“你输入我”。

客户端

class Program
{
    static void Main(string[] args)
    {
        Stopwatch stopWatch = new Stopwatch();
        stopWatch.Start();

        ServiceReference1.iRateCacheClient client = new
               ServiceReference1.iRateCacheClient();
        string returnString;
        for(int i = 0; i < 1000; i++)
            returnString = client.GetData(i);
        stopWatch.Stop();
    }
}

在那个客户端需要

  • ~2秒,1次调用getData(i)
  • 100个电话
  • ~2.4秒
  • 1000个电话
  • ~8秒

让我觉得第一个电话花了太多时间。我的用例是许多短期客户端程序将调用该服务,每次一次。编写WCF服务的全部目的是我想将函数调用从这些客户端分离到一个单独的进程;即我不想把getData()放在客户端调用的dll中。

服务呼叫的2秒“开销”是不可接受的。难道我做错了什么?我预计服务电话会在&lt; 1毫秒。我习惯了COM / DCOM;而那些开销很小。

本地服务正在使用HTTP传输。

2 个答案:

答案 0 :(得分:1)

如果只有第一个呼叫太慢,您需要检查是否是需要时间的服务器或客户端。第一次调用Web服务的速度很慢,特别是如果IIS必须启动应用程序池等等。

所以可能的对策是:

  • 保持服务正常运行,并且不要让应用程序池在很短的时间后进入休眠状态。
  • 此外,您可以使用更高效的传输协议,例如如果服务托管在另一台计算机上并且您不需要与非.NET客户端进行互操作,则为与客户端或NetTcpBinding在同一台计算机上托管的服务命名管道。当然,传输到服务和从服务传输的数据越多,协议效率就越高。有关如何使用NetNamedPipeBinding的示例,请参阅此answer
  • WCF针对SOAP服务进行了优化; SOAP协议带来一些开销,特别是如果您需要传输二进制数据,因为它们需要编码为字符串。您还可以更改为REST服务;为此,请查看ASP.NET Web API,因为WCF实现更难实现。
  • 尽可能减少到服务器的往返次数
  • 使用WCF的另一个专有和更有效的替代方法是 .NET remoting ,尽管此技术不再广泛使用。根据我的个人经验,我更喜欢WCF / ASP.NET Web API,因为它在开发和基础架构方面都得到了更好的支持。

在判断表现时,我不会对第一次请求设置过多的权重。另外,它更多地是关于“我的方法足够快”而不是“我的方法比n ms更快”。 WCF不是一种奇特的技术;有很多系统在其上运行足够快

然而,它是一种为互操作而构建的技术; COM / DCOM不是为互操作而构建的,因此可以轻松提供更好的性能。特别是COM不是一个很好的比较,因为它在同一个过程中运行; DCOM仍然使用专有协议。 WCF始终意味着您必须将数据传输到位于同一台计算机或另一台计算机上的另一个进程。这包括您需要将数据序列化为XML,传输数据并再次反序列化。所以始终存在开销。最有效的对策之一是减少对服务器的请求数量。

答案 1 :(得分:0)

首次调用WCF服务总是慢。

在一些空闲时间之后,它可能也会变慢(参见my answer如何防止它)。但对于第一次调用,处理它的唯一方法是以某种方式预热服务。例如,在应用程序初始化期间进行任何调用,然后使服务和thead池保持活动状态。

为了使它非常快,您应该使用任何类型的绑定与二进制序列化(netTcp或namedPipe,如果您使用相同的主机)和理想不同的二进制序列化器。根据我的经验,仅使用ProtoBuf .NET可以为您提供2倍更好的延迟值。 几乎您只需要将Protobuf特定属性添加到数据协定中,并通过扩展名在配置文件中启用protobuf行为。

祝你好运!