Детальное расследование исключения тайм-аута WCF - PullRequest
93 голосов
/ 11 июня 2009

У нас есть приложение с сервисом 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.exe. Мне удалось поймать одно исключение на стороне клиента. Я вижу, что его продолжительность составляет 1 минуту. Глядя на трассировку на стороне сервера, я вижу, что сервер не знает об этом исключении. Максимальная продолжительность, которую я вижу, составляет 10 секунд.

Я просмотрел активные подключения к базе данных, используя 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 позже. Я предполагаю, что RST исходит от WCF, убивающего соединение. Сообщение об исключении, которое я получаю, связано с тайм-аутом Step3.

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

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

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

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

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

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

Ответы [ 12 ]

0 голосов
/ 16 июня 2009

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

Множественное соединение с разных компьютеров / IP-адресов не должно быть проблемой.

В этом сообщении MSDN больше информации:

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

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

0 голосов
/ 15 июня 2009

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

...