WCF перестает отвечать после примерно 10 звонков (регулирование) - PullRequest
39 голосов
/ 11 апреля 2009

У меня есть служба WCF и приложение со ссылкой на службу, а с приложением у меня есть цикл, и на каждой итерации он вызывает метод в этом веб-сервисе wcf.

Проблема в том, что после примерно 9 вызовов или около того, он просто останавливается ... и если вы нажмете кнопку Pause VS, вы увидите, что он застрял на линии, где он делает вызов.

Через некоторое время ожидания это TimeoutException выдается:

Время ожидания канала запроса истекло жду ответа после 00: 00: 59,9970000. Увеличить время ожидания значение передается в запрос на запрос или увеличить значение SendTimeout на Связывание. Время, отведенное на это операция могла быть частью более длительный тайм-аут.


Я немного исследовал это и нашел некоторые решения, которые включали редактирование app.config в приложении, и вот его выдержки:

<serviceBehaviors>
    <behavior name="ThrottlingIssue">
        <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
    </behavior>
</serviceBehaviors>

.

<readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" 
 maxArrayLength="2147483647" 
 maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" /> 

Затем, после остановки отладки, через пару минут появляется сообщение об ошибке, сообщающее, что произошел катастрофический сбой .

Как я могу исправить эту проблему? У меня не было этой проблемы, когда я работал с обычным веб-сервисом.


Для справки, вот целое app.config:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <system.serviceModel>
        <behaviors>
            <serviceBehaviors>
                <behavior name="ThrottlingIssue">
                    <serviceThrottling maxConcurrentCalls="500" maxConcurrentSessions="500" />
                </behavior>
            </serviceBehaviors>
        </behaviors>
        <bindings>
            <wsHttpBinding>
                <binding name="WSHttpBinding_IDBInteractionGateway" closeTimeout="00:01:00"
                    openTimeout="00:01:00" receiveTimeout="00:10:00" sendTimeout="00:01:00"
                    bypassProxyOnLocal="false" transactionFlow="false" hostNameComparisonMode="StrongWildcard"
                    maxBufferPoolSize="524288" maxReceivedMessageSize="65536"
                    messageEncoding="Text" textEncoding="utf-8" useDefaultWebProxy="true"
                    allowCookies="false">
                    <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647"
                        maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647" />
                    <reliableSession ordered="true" inactivityTimeout="00:10:00"
                        enabled="false" />
                    <security mode="Message">
                        <transport clientCredentialType="Windows" proxyCredentialType="None"
                            realm="" />
                        <message clientCredentialType="Windows" negotiateServiceCredential="true"
                            algorithmSuite="Default" establishSecurityContext="true" />
                    </security>
                </binding>
            </wsHttpBinding>
        </bindings>
        <client>
            <endpoint address="http://localhost:28918/DBInteractionGateway.svc"
                binding="wsHttpBinding" bindingConfiguration="WSHttpBinding_IDBInteractionGateway"
                contract="DBInteraction.IDBInteractionGateway" name="WSHttpBinding_IDBInteractionGateway">
                <identity>
                    <dns value="localhost" />
                </identity>
            </endpoint>
        </client>
    </system.serviceModel>
</configuration>

[Обновление] Решение:

По-видимому, после каждого запроса вам нужно Close соединение ... Сейчас я закрываю соединение после каждого запроса, и оно работает как чудо.

Хотя я до сих пор не могу понять, что в моем app.config я установил для maxConcurrentCalls и maxConcurrentSessions значение 500, и все же я могу получить только 10. У любого есть ответ на этот вопрос. ? (возможно у меня что-то не так в моем app.config, опубликованном выше)

Ответ на поставленный выше вопрос (теперь пунктирный) объясняется тем, что я редактировал клиент app.config, а не файл конфигурации службы (web.config)

Ответы [ 6 ]

27 голосов
/ 11 апреля 2009

Количество разрешенных одновременных подключений по умолчанию - 10.
Скорее всего, ваш клиент не закрывает соединения.

Чтобы увеличить количество одновременных вызовов, вам необходимо добавить свое поведение в конфигурацию службы, а не в клиент.

3 голосов
/ 02 августа 2011

Звонок clientservice.close () решит проблему.

1 голос
/ 25 июня 2010

Эту проблему можно решить, создав одноэлементный класс в качестве интерфейса между ссылкой на веб-сервис и приложением. Затем он создаст только один экземпляр служебной ссылки.

class ServiceInterface
{
     private static ServiceInterface  _instance;
     private ServiceClient _service = new ServiceClient ;
     private ServiceInterface()
     {
       //Prevent accessing default constructor
     }

     public static ServiceInterface GetInstance()
     {

     if(_instance == null)

     {

      _instance = new ServiceInterface();

    }

        return _instance;



 }


   // You can add your functions to access web service here

    Public int PerformTask()
    {
         return _service.PerformTask();
    }
}
1 голос
/ 05 августа 2009

Я столкнулся с этой проблемой на этой неделе, и я не смог понять, что происходит. На самом деле я изменил свой вызов на мой сервис на Dispose() сервисный клиент, но, похоже, это не оказало никакого влияния. По-видимому, где-то скрывался другой сервисный звонок.

Что может быть интересно отметить, это то, что заставило меня решить, что это не проблема: этот предел не связан с фактическим количеством соединений сокетов с веб-сервисом. Когда вы достигнете предела maxConcurrentSessions, все еще будет только одно фактическое сокетное соединение . Я проверял это с netstat, что привело меня к неверному выводу. Итак, не путайте сессии с сокетами .

У нас есть интерфейсы, определенные для всех наших служб WCF, поэтому я планирую сейчас адаптировать этот шаблон в своем коде:

IMyService service = new MyServiceClient();
using (service as IDisposable)
{
    service.MyServiceMethod();
}

Также интересно то, что проблема не возникла у меня, когда службы (и веб-сайт) размещались на IIS. Конфигурация (почти) идентична, но я не мог воспроизвести это поведение на этой машине. Я думаю, это хорошо:)

@ Джон Сондерс (о присвоении переменной в using):

Обычно я помещаю присвоение переменной в оператор using. Но сгенерированный IMyService неявно не конвертируется в IDisposable. Если вы действительно хотели, чтобы задание было там, я думаю, что альтернатива будет:

IService service;
using ((service = new ServiceClient()) as IDisposable)
{
}

Это все еще оставляет проблему неправильной области видимости переменной. Ссылка на IService service непригодна, но все еще находится в области видимости. Так что это было бы лучше в этом отношении:

using (IDisposable serviceDisposable = new ServiceClient())
{
     IService service = (IService)serviceDisposable;
}

Это требует, чтобы я ввел дополнительное имя переменной. * Мех *

0 голосов
/ 19 августа 2011

После того, как я потянул мои волосы за очень подобную проблему, которая не была решена ни Close(), ни Dispose(), я хотел бы добавить простое решение, которое сделало мой день, а именно, увеличив ServicePointManager.DefaultConnectionLimit, что по умолчанию 2.

"Свойство DefaultConnectionLimit устанавливает максимальное число одновременных соединений по умолчанию, которое объект ServicePointManager назначает свойству ConnectionLimit при создании объектов ServicePoint."

В моем случае мое приложение успешно подключилось к моей удаленной службе 2 раза, с третьей попытки оно просто не пыталось подключиться к службе. Вместо этого он некоторое время ждал, пока не вышло время с тем же сообщением об ошибке, что и в вопросе выше. Увеличение DefaultConnectionLimit решило это. Чтобы добавить к разочарованию, это поведение было несколько случайным - в одном случае из 10 веб-сервис был успешно запущен несколько раз (> 2).

Решение порождает и дополнительно обсуждает эти два потока: wcf-timeout-исключение-подробное исследование и wcf-service-throttling . решил мою проблему.

0 голосов
/ 11 апреля 2009

Можете ли вы настроить трассировку и запустить цикл? Может случиться так, что канал выйдет из строя и приведет к истечению времени ожидания клиента.

...