2009-06-11 4 views
92

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

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

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

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

+0

Джейсон - вы когда-нибудь решить эту проблему? Была ли настройка DefaultConnectionLimit? – SFun28

+2

@JasonKealey - В отличие от многих других вопросов, вас нельзя обвинять в том, что вы не пытаетесь для себя, прежде чем публиковать вопрос :) Мне нравится, что ваш вопрос настолько детализирован и включает в себя все важные детали. Симптомы, которые вы описываете, очень похожи на мои, поэтому я надеюсь, что решение будет таким же :) :) –

ответ

46

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

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

здесь оригинальный вопрос и ответ WCF Service Throttling

Update:

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

Более того, вы можете иметь его в app.config файл, а как следующий

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

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

+1

@Jason: Если вы программист на сервере, вы знаете, насколько важно поддерживать масштабируемость сервера в ваших руках, а также тот, кто в настоящее время испытывает проблему параллелизма даже после использования выше. Пожалуйста, если вы можете рассмотреть следующий вопрос: http://stackoverflow.com/questions/2637175/wcf-network-cost короче, я страдаю с задержкой в ​​31 мс между клиентом и сервером и вам необходимо его уменьшить. –

+3

Это занял год, но я, наконец, провела еще один стресс-тест приложения с этим набором флагов. Проблема кажется решенной, поэтому я даю вам лучший ответ. Я не удивлюсь, что это была последняя часть загадки, которая требовалась, но чтобы все остальные элементы были на месте, чтобы не допустить ошибки. Огромное спасибо! –

2

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

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

+0

Я пробовал это. Независимо от тайм-аута, который я поставил, он все еще не работает, но это бессмысленно, потому что операция не так долго и потому, что все остальные клиенты, которые выполняют одни и те же запросы, работают в это время. –

+0

Мои тесты показали, что OperationTimeout просто переопределяет ReceiveTimeout из конфигурации. Таким образом, это бесполезно. – dudeNumber4

0

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

+0

Знаете ли вы о каких-либо инструментах, которые были более свежими, чем устаревший инструментарий SOAP, который облегчил бы мне записывать эту информацию в вызовы WCF? –

+0

Вы можете попробовать soapUI http://www.soapui.org/. – Philippe

+0

*** SOAP Toolkit *** is * 'derecated' * – Kiquenet

0

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

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

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

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

Отъезд MaxConcurrentSession sproperty.

+0

Я чувствую, что это то, что происходит, из всего, что я видел, однако у меня есть (на сервере): Был ли монитор производительности или журнал IIS, который я мог бы контролировать, чтобы увидеть, происходит ли это? –

0

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

+0

Я попробовал SvcTraceViewer и единственным исключением, о котором сообщалось, был тайм-аут (на клиенте). На сервере ничего не сообщалось. –

+0

Откройте все параметры трассировки, вы можете не открывать все параметры трассировки. Кроме того, проверьте как трассировку событий, так и файлы трассировки сообщений. –

3

Если вы уже не пробовали - инкапсулируйте свои операции 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 фактически отправляет ответы.

+0

У меня есть вход на сервер - в этом нет ошибки. Я бегу WireShark прямо сейчас, чтобы посмотреть, что я могу найти. Учитывая большой объем трафика, это будет боль для анализа, но я отчитаюсь, если найду что-нибудь. –

+0

Я провел WireShark за последние шесть часов и собрал около 60 тыс. Кадров. Сегодня единственным клиентом сообщил этот клиент. Я видел TCP-соединение, помеченное как RST (сброс), по-видимому, после отправки сообщения об ошибке, который, вероятно, является WCF, который завершает соединение. Я сохранил полезную нагрузку (525k) на диск. Я проверил, что было 87 других вызовов с подобными размерами полезной нагрузки. Я видел несколько повторных передач TCP, но видел и некоторые другие вызовы (это не сработало). Запугав вопрос о моем сетевом оборудовании + кабелях. –

+0

Даже в локальной сети наличие TCP Retransmits не обязательно плохое. Если можно физически подключить две конечные точки к одному коммутатору, то это может стоить того, чтобы выстрелить, но я не буду надеяться, что это исправит. Если вы можете - создать очень основное клиентское приложение, которое просто передает некоторый трафик назад и вперед на ваш сервер, и ничего больше. Это может помочь устранить любые проблемы в вашем приложении, которые могут вызывать тайм-ауты. – 2009-06-19 15:50:29

2

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

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

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

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

UPDATE: Я не уверен, что это поможет вам, но инструмент 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> 

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

0

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

2

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

2

Я только что решил проблему. Я обнаружил, что узлы в файле 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>, значение «режим» атрибут не является «None». Если ваше значение - «Транспорт», возникает ошибка.

+0

Не влияет ли это на безопасность? Если это так, это не может быть решением для большинства реальных приложений – Veverke

0

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