简体   繁体   English

如何在使用多个代理客户端时修复WCF中的basicHttpBinding?

[英]How to fix basicHttpBinding in WCF when using multiple proxy clients?

[Question seems a little long but please have patience. [问题似乎有点长,但请耐心等待。 It has sample source to explain the problem.] 它有样本来源来解释这个问题。]

Consider following code which is essentially a WCF host: 请考虑以下基本上是WCF主机的代码:

[ServiceContract (Namespace = "http://www.mightycalc.com")]
interface ICalculator
{
    [OperationContract]
    int Add (int aNum1, int aNum2);
}

[ServiceBehavior (InstanceContextMode = InstanceContextMode.PerCall)]
class Calculator: ICalculator
{
    public int Add (int aNum1, int aNum2) {
        Thread.Sleep (2000); //Simulate a lengthy operation
        return aNum1 + aNum2;
    }
}

class Program
{
    static void Main (string[] args) {
        try {
            using (var serviceHost = new ServiceHost (typeof (Calculator))) {
                var httpBinding = new BasicHttpBinding (BasicHttpSecurityMode.None);
                serviceHost.AddServiceEndpoint (typeof (ICalculator), httpBinding, "http://172.16.9.191:2221/calc");

                serviceHost.Open ();
                Console.WriteLine ("Service is running. ENJOY!!!");
                Console.WriteLine ("Type 'stop' and hit enter to stop the service.");
                Console.ReadLine ();

                if (serviceHost.State == CommunicationState.Opened)
                    serviceHost.Close ();
            }
        }
        catch (Exception e) {
            Console.WriteLine (e);
            Console.ReadLine ();
        }
    }
}

Also the WCF client program is: WCF客户端程序也是:

class Program
{
    static int COUNT = 0;
    static Timer timer = null;

    static void Main (string[] args) {
        var threads = new Thread[10];

        for (int i = 0; i < threads.Length; i++) {
            threads[i] = new Thread (Calculate);
            threads[i].Start (null);
        }

        timer = new Timer (o => Console.WriteLine ("Count: {0}", COUNT), null, 1000, 1000);
        Console.ReadLine ();
        timer.Dispose ();
    }

    static void Calculate (object state)
    {
        var c = new CalculatorClient ("BasicHttpBinding_ICalculator");
        c.Open ();

        while (true) {
            try {
                var sum = c.Add (2, 3);
                Interlocked.Increment (ref COUNT);
            }
            catch (Exception ex) {
                Console.WriteLine ("Error on thread {0}: {1}", Thread.CurrentThread.Name, ex.GetType ());
                break;
            }
        }

        c.Close ();
    }
}

Basically, I am creating 10 proxy clients and then repeatedly calling Add service method on separate threads. 基本上,我正在创建10个代理客户端,然后在不同的线程上重复调用Add service方法。 Now if I run both applications and observe opened TCP connections using netstat, I find that: 现在如果我运行两个应用程序并使用netstat观察打开的TCP连接,我发现:

  • If both client and server are running on same machine, number of tcp connections are equal to number of proxy objects. 如果客户端和服务器都在同一台计算机上运行,​​则tcp连接数等于代理对象数。 It means all requests are being served in parallel. 这意味着所有请求都是并行提供的。 Which is good. 这很好。
  • If I run server on a separate machine, I observed that maximum 2 TCP connections are opened regardless of the number of proxy objects I create. 如果我在一台单独的机器上运行服务器,我发现无论我创建的代理对象的数量是多少,都会打开最多2个TCP连接。 Only 2 requests run in parallel. 只有2个请求并行运行。 It hurts the processing speed badly. 它严重损害了处理速度。
  • If I switch to net.tcp binding, everything works fine (a separate TCP connection for each proxy object even if they are running on different machines). 如果我切换到net.tcp绑定,一切正常(每个代理对象的单独TCP连接,即使它们在不同的机器上运行)。

I am very confused and unable to make the basicHttpBinding use more TCP connections. 我很困惑,无法使basicHttpBinding使用更多的TCP连接。 I know it is a long question, but please help! 我知道这是一个很长的问题,但请帮忙!

After spending 2 days on this problem, I found the solution so let me document it here. 在这个问题上花了2天后,我找到了解决方案,所以让我在这里记录下来。

Actually the problem is not of service configuration or throttling. 实际上问题不在于服务配置或限制。 Actually server (WCF host) cannot do anything if a client is not making connection to it. 实际上,如果客户端没有与它建立连接,服务器(WCF主机)就无法执行任何操作。 In this case WCF client was not making more than 2 connections. 在这种情况下,WCF客户端没有超过2个连接。 I tried basicHttpBinding, WsHttpBinding and even the good old web reference (asmx) method. 我尝试了basicHttpBinding,WsHttpBinding甚至是旧的Web引用(asmx)方法。 Every case failed to make more than 2 connections. 每个案例都没有超过2个连接。

The root of this effect lies in ServicePointManager.DefaultConnectionLimit property which has a default value of 2. This class is in System.Net namespace which is responsible for making Http connections. 此效果的根源在于ServicePointManager.DefaultConnectionLimit属性,其默认值为2.此类位于System.Net命名空间中,该命名空间负责进行Http连接。 Apparently both WCF and ASMX web reference use System.Net namespace for doing their HTTP stuff. 显然,WCF和ASMX Web引用都使用System.Net命名空间来执行HTTP操作。 This explains why I couldn't make multiple service request even after creating multiple proxy clients in multiple threads. 这解释了为什么即使在多个线程中创建多个代理客户端之后我也无法发出多个服务请求。

In summary, the solution is to set ServicePointManager.DefaultConnectionLimit to the number of concurrent calls you want to make from your client . 总之,解决方案是将ServicePointManager.DefaultConnectionLimit设置为您要从客户端进行的并发调用的数量。

Check out server throttling - it's a server-side behavior which you can apply to your server-side config: 检查服务器限制 - 这是一个服务器端行为,您可以将其应用于服务器端配置:

<system.serviceModel>
    <services>
      <service 
        name="Microsoft.WCF.Documentation.SampleService"
        behaviorConfiguration="Throttled" >
        <host>
          <baseAddresses>
            <add baseAddress="http://localhost:8080/SampleService"/>
          </baseAddresses>
        </host>
        <endpoint
          address=""
          binding="wsHttpBinding"
          contract="Microsoft.WCF.Documentation.ISampleService"
         />
        <endpoint
          address="mex"
          binding="mexHttpBinding"
          contract="IMetadataExchange"
         />
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="Throttled">
          <serviceThrottling 
            maxConcurrentCalls="1" 
            maxConcurrentSessions="1" 
            maxConcurrentInstances="1" />
          <serviceMetadata httpGetEnabled="true" httpGetUrl="" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
  </system.serviceModel>

See this blog post for more detailed info, or check the MSDN docs on Service Throttling 有关更多详细信息,请参阅此博客文章 ,或查看有关服务限制MSDN文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM