Как исправить basicHttpBinding в WCF при использовании нескольких прокси-клиентов? - PullRequest
3 голосов
/ 17 марта 2010

[Вопрос кажется немного длинным, но, пожалуйста, наберитесь терпения. У него есть пример источника, чтобы объяснить проблему.]

Рассмотрим следующий код, который по сути является хостом 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 ();
        }
    }
}

Также клиентская программа 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 ();
    }
}

По сути, я создаю 10 прокси-клиентов, а затем неоднократно вызываю метод Add service в отдельных потоках. Теперь, если я запускаю оба приложения и наблюдаю открытые TCP-соединения с помощью netstat, я нахожу, что:

  • Если клиент и сервер работают на одном компьютере, количество соединений tcp равно количеству прокси-объектов. Это означает, что все запросы обслуживаются параллельно. Что хорошо.
  • Если я запускаю сервер на отдельном компьютере, я заметил, что открыты максимум 2 TCP-соединения независимо от количества создаваемых прокси-объектов. Только 2 запроса выполняются параллельно. Это сильно ухудшает скорость обработки.
  • Если я переключаюсь на привязку net.tcp, все работает нормально (отдельное TCP-соединение для каждого прокси-объекта, даже если они работают на разных машинах).

Я очень запутался и не могу заставить базовый HttpBinding использовать больше TCP-соединений. Я знаю, что это длинный вопрос, но, пожалуйста, помогите!

Ответы [ 2 ]

9 голосов
/ 18 марта 2010

Потратив 2 дня на эту проблему, я нашел решение, поэтому позвольте мне документировать его здесь.

На самом деле проблема не в конфигурации службы или регулировании. На самом деле сервер (хост WCF) ничего не может сделать, если клиент не подключается к нему. В этом случае клиент WCF не делал более двух подключений. Я попробовал basicHttpBinding, WsHttpBinding и даже старый добрый метод веб-ссылок (asmx). В каждом случае не удалось установить более 2 подключений.

Корень этого эффекта лежит в ServicePointManager.DefaultConnectionLimit свойстве со значением по умолчанию, равным 2. Этот класс находится в пространстве имен System.Net, отвечающем за подключение Http. Очевидно, что и веб-ссылки WCF и ASMX используют пространство имен System.Net для выполнения своих функций HTTP. Это объясняет, почему я не мог сделать несколько запросов на обслуживание даже после создания нескольких прокси-клиентов в нескольких потоках.

Таким образом, решение состоит в том, чтобы установить ServicePointManager.DefaultConnectionLimit на количество одновременных вызовов, которые вы хотите сделать от вашего клиента .

1 голос
/ 17 марта 2010

Проверьте регулирование сервера - это поведение на стороне сервера, которое вы можете применить к конфигурации сервера:

<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>

См. сообщение в блоге для получения более подробной информации или проверьте документы MSDN по регулированию обслуживания

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...