C# WCF客户端性能问题

C# WCF客户端性能问题,c#,wcf,C#,Wcf,我有一个应用程序,它应该能够向我的wcf服务发送数百个并发请求。该服务正在公开http联合绑定 目前,我使用单个客户端和TPL在多个线程上发送请求。我还将system.net max connections设置更改为1000,这样windows就不会将wcf限制为atmost 2并发请求 我可以看到,初始请求需要更多的时间,因为他们正在获取身份验证令牌等,然后请求时间通常开始显著减少,但随后我会间歇性地看到一些峰值,这些峰值与我拥有的服务器日志不相关 我想知道这是否是接近高通量、高可扩展客户机的

我有一个应用程序,它应该能够向我的wcf服务发送数百个并发请求。该服务正在公开http联合绑定

目前,我使用单个客户端和TPL在多个线程上发送请求。我还将system.net max connections设置更改为1000,这样windows就不会将wcf限制为atmost 2并发请求

我可以看到,初始请求需要更多的时间,因为他们正在获取身份验证令牌等,然后请求时间通常开始显著减少,但随后我会间歇性地看到一些峰值,这些峰值与我拥有的服务器日志不相关

我想知道这是否是接近高通量、高可扩展客户机的最佳方式

我曾尝试在多个线程之间使用共享客户端代理,并在多个线程之间使用共享ChannelFactory。所有线程都使用TPL完成

显示了绑定

<basicHttpBinding>
        <binding name="Binding1" openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:05:00" closeTimeout="00:01:00" allowCookies="false" bypassProxyOnLocal="false" hostNameComparisonMode="StrongWildcard" maxBufferSize="2147483647" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text" textEncoding="utf-8" transferMode="Buffered" useDefaultWebProxy="true">
          <readerQuotas maxDepth="32" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
          <security mode="TransportWithMessageCredential">
            <transport clientCredentialType="None" proxyCredentialType="None" realm=""/>
            <message clientCredentialType="UserName" algorithmSuite="Default"/>
          </security>
        </binding>
      </basicHttpBinding>

WCF服务和使用WCF客户端(直接使用ClientBase或ChannelFactory)时出现的一些生产性能问题是由于.NET垃圾收集器由于对象处理不及时而被迫执行大量工作造成的。我将使用性能监视器在运行时检查.NET垃圾收集器的行为,看看这是否是导致峰值的原因

如果是GC问题,那么您需要对您的服务和客户机代码进行检查。在服务上,确保对象实例范围尽可能有限。这有助于确保实例大部分是在Gen0中进行的垃圾收集,而Gen0是最常见的。还应审查客户机代码,但这在服务代码中尤为重要


此外,在这两种服务中,尤其是在客户端上,确保使用语句将实现IDisposable的对象实例正确包装在
中,WCF客户端实例除外。要正确处理WCF客户机,请查看这一良好模式。如果您使用的是依赖项注入容器,那么这可能会很棘手。您可以搜索“WCF不使用”以获取有关原因的详细信息。BasicHttpBinding和WsHttpBinding的某些配置可以处理草率的处理,但任何使用会话的绑定都容易出现GC问题。

WCF服务和WCF客户端(直接使用ClientBase或ChannelFactory)都会出现一些生产性能问题是由于.NET垃圾回收器由于对象处理不及时而被迫执行大量工作。我将使用性能监视器在运行时检查.NET垃圾收集器的行为,看看这是否是导致峰值的原因

如果是GC问题,那么您需要对您的服务和客户机代码进行检查。在服务上,确保对象实例范围尽可能有限。这有助于确保实例大部分是在Gen0中进行的垃圾收集,而Gen0是最常见的。还应审查客户机代码,但这在服务代码中尤为重要


此外,在这两种服务中,尤其是在客户端上,确保使用
语句将实现IDisposable的对象实例正确包装在
中,WCF客户端实例除外。要正确处理WCF客户机,请查看这一良好模式。如果您使用的是依赖项注入容器,那么这可能会很棘手。您可以搜索“WCF不使用”以获取有关原因的详细信息。BasicHttpBinding和WsHttpBinding的某些配置可以处理草率的处理,但是任何使用会话的绑定都容易出现GC问题。

您提到您使用的是单个客户端实例,然后使用TPL展开工作。WCF客户端实例在技术上不是线程安全的。创建客户机的成本非常低廉,只要在创建新实例时
Close()

其次,您不应该单独使用TPL来获得并发性。当您进行WCF调用时,都是关于网络I/O和等待来自服务器的响应。你需要确保你在你的客户身上所做的就是使用。然后,您可以将它们与TPL的
Task.Factory.fromsync
结合起来,将调用返回后可能需要执行的任何其他工作流链接在一起。例如:

[ServiceContract]
public interface IMyService
{
    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginDoSomething();
    SomeResultType EndDoSomething(IAsyncResult result);
}

// Somewhere in the client app you store your channel factory (these are "expensive", these you cache)
ChannelFactory<IMyService> channelFactory = new ChannelFactory<IMyService>();

public void MyClientMethod()
{
   // Create a client channel
   IMyService myServiceChannel = channelFactory.CreateChannel();

   // Use TPL's FromAsync to invoke the async WCF call and wrap that up with the familiar Task API
   Task<SomeResultType>.Factory.FromAsync(myServiceChannel.BeginDoSomething
                                          myServiceChannel.EndDoSomething,
                                          null)
                               .ContinueWith(antecdent =>
                               {
                                    try
                                    {
                                        // NOTE: exception will be thrown here if operation failed
                                        SomeResultType result = antecedent.Result;

                                        // ... continue processing the result ...
                                    }
                                    finally
                                    {
                                        // NOTE: depending on your configuration you might want to watch for errors and .Abort() here too
                                        ((IClientChannel)myServiceChannel).Close();
                                    }
                               });      
}
[服务合同]
公共接口IMyService
{
[操作契约(AsyncPattern=true)]
IAsyncResult begindomething();
SomeResultType EndDoSomething(IAsyncResult结果);
}
//在客户端应用程序的某个地方,您存储了您的频道工厂(这些是“昂贵的”,您可以缓存这些)
ChannelFactory ChannelFactory=新的ChannelFactory();
public void MyClientMethod()
{
//创建一个客户端通道
IMyService myservicecchannel=channelFactory.CreateChannel();
//使用TPL的FromAsync调用异步WCF调用,并使用熟悉的任务API将其包装起来
Task.Factory.fromsync(myServiceChannel.BeginDoSomething
myServiceChannel.EndDoSomething,
空)
.ContinueWith(先行=>
{
尝试
{
//注意:如果操作失败,将在此处引发异常
SomeResultType result=antecedent.result;
//…继续处理结果。。。
}
最后
{
//注意:根据您的配置,您可能希望在此处监视错误和.Abort()
((IClientChannel)myServiceChannel.Close();