Подробное исследование исключения таймаута WCF


у нас есть приложение, которое имеет службу WCF (*.svc) работает на IIS7 и различных клиентах, запрашивающих службу. На сервере работает Win 2008 Server. Клиенты работают под управлением Windows 2008 Server или Windows 2003 server. Я получаю следующее исключение, которое я видел на самом деле может быть связано с большим количеством потенциальных проблем в WCF.

System.TimeoutException: The request channel timed out while waiting for a reply after 00:00:59.9320000. Increase the timeout value passed to the call to Request or increase the SendTimeout value on the Binding. The time allotted to this operation may have been a portion of a longer timeout. ---> System.TimeoutException: The HTTP request to 'http://www.domain.com/WebServices/myservice.svc/gzip' has exceeded the allotted timeout of 00:01:00. The time allotted to this operation may have been a portion of a longer timeout. 

я увеличил время ожидания до 30 минут, и ошибка все еще произошла. Это говорит мне, что что-то еще в игре, потому что количество данных никогда не может занять 30 минут для загрузки или загрузки.

ошибка приходит и уходит. На данный момент это происходит чаще. Кажется, не имеет значения, если у меня есть 3 клиента, работающих одновременно или 100, это все еще происходит время от времени. Большую часть времени нет тайм-аутов, но я все еще получаю несколько в час. Ошибка происходит от любого из методов, которые вызываются. Один из этих методов не имеет параметров и возвращает данные. Другой берет в много данных в качестве параметра, но выполняется асинхронно. Ошибки всегда исходят от клиента и никогда не ссылаются на какой-либо код на сервере в трассировке стека. Это всегда заканчивается:

 at System.Net.HttpWebRequest.GetResponse()
  at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)

на сервере: Я пробовал (и в настоящее время есть) следующие настройки привязки:

maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"

это, кажется, не влияют.

я пробовал (и в настоящее время есть) следующие настройки регулирования:

<serviceThrottling maxConcurrentCalls="1500"   maxConcurrentInstances="1500"    maxConcurrentSessions="1500"/>

похоже, что нет есть влияние.

в настоящее время у меня есть следующие настройки для службы WCF.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]

я ConcurrencyMode.Multiple на некоторое время, и ошибка все еще произошла.

я попытался перезапустить IIS, перезапустить мой базовый SQL Server, перезапустить машину. Все это, кажется, не имеет никакого влияния.

я попытался отключить Брандмауэр Windows. Это, кажется, не оказывает влияния.

на клиенте, у меня есть эти параметры:

maxReceivedMessageSize="2147483647"

<system.net>
    <connectionManagement>
    <add address="*" maxconnection="16"/>
</connectionManagement> 
</system.net>

мой клиент закрывает соединения:

var client = new MyClient();

try
{
    return client.GetConfigurationOptions();
}
finally
{
    client.Close();
}

я изменил настройки реестра, чтобы разрешить больше исходящих соединений:

MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

я только недавно попробовал SvcTraceViewer.исполняемый. Мне удалось поймать одно исключение на стороне клиента. Я вижу, что его продолжительность составляет 1 минуту. Глядя на трассировку на стороне сервера, я вижу, что сервер не знает об этом исключении. Максимальная продолжительность, которую я вижу, составляет 10 секунд.

I посмотрели на активные подключения к базе данных с помощью exec sp_who на сервере. У меня есть только несколько (2-3). Я посмотрел на TCP-соединения от одного клиента с помощью TCPview. Обычно это около 2-3, и я видел до 5 или 6.

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

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

Спасибо за ваше время!

дополнительная информация добавлена 20 июня:

мое приложение WCF делает что-то похожее на следующее.

while (true)
{
   Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
   Step2GetWorkUnitFromServerViaWCF();
   DoWorkLocally(); // takes 5-15minutes. 
   Step3SendBackResultsToServerViaWCF();
}

используя WireShark, я видел, что при возникновении ошибки у меня есть пять повторных передач TCP, за которыми позже следует сброс TCP. Я предполагаю, что первый исходит от WCF, убивая соединение. Отчет об исключении, который я получаю, - это время ожидания шага 3.

я обнаружил это глядя на поток tcp " tcp.поток eq 192". Затем я расширил свой фильтр до " tcp.поток eq 192 и http и http.запрос.метод eq POST " и увидел 6 сообщений во время этого потока. Это казалось странным, поэтому я проверил с другим потоком, таким как tcp.поток eq 100. У меня было три сообщения, что кажется немного более нормальным, потому что я делаю три звонка. Тем не менее, я закрываю свое соединение после каждого вызова WCF, поэтому я ожидал бы один вызов на поток (но я мало знаю о TCP).

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

1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2

я предполагаю, что два параллельных клиента используют одно и то же соединение, поэтому я видел дубликаты. Тем не менее, у меня есть еще несколько вопросов, которые я не могу понять:

a) почему пакет поврежден? Случайная сетевая случайность-может быть? Нагрузка в сжатом виде, используя этот пример кода: http://msdn.microsoft.com/en-us/library/ms751458.aspx - Может ли код быть глючным время от времени при одновременном использовании? Я должен проверить без библиотеки gzip.

b) почему я вижу, что Шаг 1 и Шаг 2 выполняются после истечения времени ожидания поврежденной операции? Мне кажется, что эти операции не должны были произойти. Может быть, я не смотрю на правильный поток, потому что мое понимание TCP является ошибочным. У меня есть другие потоки, которые происходят одновременно. Я должен исследуйте другие потоки-быстрый взгляд на потоки 190-194 показывает, что сообщение Step3 имеет правильные данные полезной нагрузки (не повреждено). Толкает меня, чтобы снова посмотреть в библиотеке с помощью gzip.

12 92

12 ответов:

Если вы используете клиент .Net, то вы, возможно, не установили

//This says how many outgoing connection you can make to a single endpoint. Default Value is 2
System.Net.ServicePointManager.DefaultConnectionLimit = 200;

вот оригинальный вопрос и ответ регулирование службы WCF

обновление:

эта конфигурация идет в клиентском приложении .Net может быть при запуске или всякий раз, но перед началом тестов.

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

<system.net>
    <connectionManagement>
      <add maxconnection = "200" address ="*" />
    </connectionManagement>
  </system.net>

Если вы еще не пробовали - инкапсулируйте свои серверные операции WCF в блоках try/finally и добавьте ведение журнала, чтобы убедиться, что они действительно возвращаются.

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

Wireshark или другой подобный инструмент захвата пакетов может быть весьма полезным на данном этапе. Я предполагаю, что это работает через HTTP на стандартном порту 80.

запустите Wireshark на клиенте. В параметрах при запуске захвата установите фильтр захвата в tcp http and host service.example.com - Это позволит уменьшить количество нерелевантного трафика.

Если вы можете, измените свой клиент, чтобы уведомить вас о точном времени начала вызова и времени, когда произошел тайм-аут. Или просто внимательно следить за ним.

когда вы получаете сообщение об ошибке, то вы можете тралить через журналы Wireshark, чтобы найти начало вызова. Щелкните правой кнопкой мыши на первый пакет если ваш клиент звонит на него (должно быть что-то вроде GET /service.svc или почта / сервис.svc) и выберите следовать потоку TCP.

Wireshark будет декодировать весь HTTP-диалог, поэтому вы можете убедиться, что WCF действительно отправляет ответы.

от:http://www.codeproject.com/KB/WCF/WCF_Operation_Timeout_.aspx

чтобы избежать этой ошибки тайм-аута, нам нужно к настройка OperationTimeout свойство для прокси в клиенте WCF код. Эта конфигурация что-то новые в отличие от других конфигураций такие как отправить тайм-аут, тайм-аут получения и т. д., который я обсуждал в начале статья. Чтобы установить этот тайм-аут операции конфигурация свойства, мы должны литой нашего сервера в IContextChannel в Клиентское приложение WCF перед вызовом методы контракта операции.

У меня очень похожая проблема. В прошлом, это было связано с проблемами сериализации. Если у вас все еще есть эта проблема, вы можете проверить, что вы можете правильно сериализовать возвращаемые объекты. В частности, если вы используете объекты Linq-to-Sql, которые имеют отношения, существуют известные проблемы сериализации, если вы помещаете обратную ссылку на дочерний объект в родительский объект и помечаете эту обратную ссылку как элемент DataMember.

вы можете проверить сериализация путем написания консольного приложения, которое сериализует и десериализует ваши объекты с помощью DataContractSerializer на стороне сервера и любых методов сериализации, используемых вашим клиентом. Например, в нашем текущем приложении у нас есть клиенты WPF и Compact Framework. Я написал консольное приложение, чтобы убедиться, что я могу сериализовать с помощью DataContractSerializer и десериализовать с помощью XmlDesserializer. Вы можете попробовать это.

кроме того, если вы возвращаете объекты Linq-to-Sql, которые есть дочерние коллекции, вы можете попытаться убедиться, что вы охотно загрузили их на стороне сервера. Иногда из-за ленивой загрузки возвращаемые объекты не заполняются и могут вызвать поведение, которое вы видите, когда запрос отправляется методу службы несколько раз.

Если вы решили эту проблему, я хотел бы услышать, как потому что я застрял с ним тоже. Я проверил, что моя проблема не сериализация, поэтому я в недоумении.

обновление: я не конечно, если это поможет вам любой, но инструмент просмотра трассировки службы просто решил мою проблему после 5 дней очень похожего опыта на ваш. Настроив трассировку, а затем посмотрев на необработанный XML, я нашел исключения, которые вызывали мои проблемы с сериализацией. Это было связано с объектами Linq-to-SQL, которые иногда имели больше дочерних объектов, чем могли быть успешно сериализованы. Добавление следующего в ваш интернет.конфигурационный файл должен включать трассировку:

<sharedListeners>
    <add name="sharedListener"
         type="System.Diagnostics.XmlWriterTraceListener"
         initializeData="c:\Temp\servicetrace.svclog" />
  </sharedListeners>
  <sources>
    <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" >
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
  </sources>

полученный файл может откройте с помощью инструмента просмотра трассировки службы или просто в IE, чтобы проверить результаты.

вы закрываете соединение со службой WCF между запросами? Если вы этого не сделаете, вы увидите этот точный тайм-аут (в конечном итоге).

Я только что решил эту проблему.Я обнаружил, что узлы в приложении.конфигурационный файл настроен неправильно.

<client>
<endpoint name="WCF_QtrwiseSalesService" binding="wsHttpBinding" bindingConfiguration="ws" address="http://cntgbs1131:9005/MyService/TGE.ISupplierClientManager" contract="*">
</endpoint>
</client>

<bindings>
    <wsHttpBinding>
        <binding name="ws" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            <**security mode="None">**
                <transport clientCredentialType="None"></transport>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

подтвердите свою конфигурацию в узле <security>, значение атрибута " mode "равно"None". Если ваше значение "транспорт",возникает ошибка.

вы пробовали использовать clientVia чтобы увидеть отправленное сообщение, используйте SOAP toolkit или что-то подобное? Это может помочь увидеть, если ошибка исходит от самого клиента или откуда-то еще.

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

вы также получите эту ошибку, если вы передаете объект обратно клиенту, который содержит свойство типа enum, которое не задано по умолчанию, и это перечисление не имеет значения, которое сопоставляется с 0. я.е enum MyEnum{ a=1, b=2};

похоже, что это сообщение об исключении является довольно общим и может быть получено по разным причинам. Мы столкнулись с этим при развертывании клиента на машинах Windows 8.1. Наш клиент WCF работает внутри службы windows и постоянно опрашивает службу WCF. Служба windows работает под управлением пользователя, не являющегося администратором. Проблема была устранена путем установки clientCredentialType в "Windows" в конфигурации WCF, чтобы разрешить проверку подлинности для прохождения, как в следующем:

      <security mode="None">
        <transport clientCredentialType="Windows" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>

Я не эксперт WCF, но мне интересно, если вы не работаете в защиту DDOS на IIS. Я знаю по опыту, что если вы запускаете кучу одновременных подключений от одного клиента к серверу в какой-то момент сервер перестает отвечать на вызовы, поскольку он подозревает атаку DDOS. Он также будет удерживать соединения открытыми до тех пор, пока они не выйдут из строя, чтобы замедлить клиента в его атаках.

множественное соединение приходя от различных машин / ИП не должно быть а проблема, однако.

в этом сообщении MSDN есть дополнительная информация:

http://msdn.microsoft.com/en-us/library/bb463275.aspx

Проверьте свойство MaxConcurrentSession.