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