У нас есть приложение, которое имеет службу WCF (*.svc), работающую на IIS7, и различные клиенты, запрашивающие эту службу. На сервере работает Win 2008 Server. Клиенты работают либо на сервере Windows 2008 Server, либо на Windows 2003. Я получаю следующее исключение, которое, как я видел, фактически может быть связано с большим количеством потенциальных проблем 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 июня:
My WCF-приложение делает что-то похожее на следующее.
while (true)
{
Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
Step2GetWorkUnitFromServerViaWCF();
DoWorkLocally(); // takes 5-15minutes.
Step3SendBackResultsToServerViaWCF();
}
Используя WireShark, я видел, что когда возникает ошибка, у меня есть пять повторных передач TCP, за которыми позже следует TCP reset. Я предполагаю, что 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.