Детальное расследование исключения тайм-аута 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 ]

49 голосов
/ 16 апреля 2010

Если вы используете .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 может быть при запуске или в любое время, но до начала ваших испытаний

Кроме того, вы можете иметь его в файле app.config, например: 1014 *

<system.net>
    <connectionManagement>
      <add maxconnection = "200" address ="*" />
    </connectionManagement>
  </system.net>
3 голосов
/ 17 июня 2009

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

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

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

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

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

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

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

2 голосов
/ 18 ноября 2011

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

<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". Если ваше значение равно «Транспорт», возникает ошибка.

2 голосов
/ 05 апреля 2011

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

2 голосов
/ 20 августа 2009

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

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

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

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

ОБНОВЛЕНИЕ: Я не уверен, поможет ли это вам, но инструмент Service Trace Viewer только что решил мою проблему после 5 дней схожего с вашим опытом. Установив трассировку, а затем просмотрев необработанный XML, я обнаружил исключения, которые вызывали мои проблемы с сериализацией. Это было связано с объектами Linq-to-SQL, которые иногда имели больше дочерних объектов, чем могли быть успешно сериализованы. Добавление следующего в ваш файл web.config должно включить трассировку:

<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, чтобы просмотреть результаты.

2 голосов
/ 11 июня 2009

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

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

1 голос
/ 20 апреля 2010
0 голосов
/ 13 июня 2014

Похоже, это сообщение об исключении является довольно общим и может быть получено по разным причинам. Мы столкнулись с этим при развертывании клиента на компьютерах с 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>
0 голосов
/ 26 февраля 2011

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

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

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

...