В WCF исключение timeout детальное расследование

у нас есть приложение, которое имеет службу WCF (*.svc) работает на IIS7 и различных клиентах, запрашивающих службу. На сервере работает сервер Win 2008. Клиенты работают под управлением 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. 

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

я обнаружил это посмотрев на поток tcp " tcp.эквалайзер поток 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) почему пакет поврежден? Случайная сетевая случайность-может быть? Нагрузка gzipped используя этот код образца: http://msdn.microsoft.com/en-us/library/ms751458.aspx - Может ли код быть багги время от времени при одновременном использовании? Я должен протестировать без библиотеки gzip.

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

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

кроме того, вы можете иметь его в приложении.файл config как хорошо, как после

<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 или POST / service.svc) и выберите следовать потоку TCP.

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


from:http://www.codeproject.com/KB/WCF/WCF_Operation_Timeout_.aspx

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


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

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

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

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

обновление: я не конечно, если это поможет вам, но сервис Trace Viewer Tool только что решил мою проблему после 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>

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


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


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

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

множественное соединение, поступающее с разных машин / IP, не должно быть проблема, однако.

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

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

Проверьте MaxConcurrentSession sproperty.