Temos um aplicativo que possui um serviço WCF (* .svc) em execução no IIS7 e vários clientes que consultam o serviço. O servidor está executando o Win 2008 Server. Os clientes estão executando o Windows 2008 Server ou o Windows 2003 Server. Estou recebendo a seguinte exceção, que percebi que pode, na verdade, estar relacionada a um grande número de possíveis problemas do 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.
Aumentei o tempo limite para 30 minutos e o erro ainda ocorreu. Isso me diz que algo mais está em jogo, porque a quantidade de dados nunca levaria 30 minutos para ser carregada ou baixada.
O erro vem e vai. No momento, é mais frequente. Não parece importar se eu tenho 3 clientes rodando simultaneamente ou 100, ainda ocorre de vez em quando. Na maioria das vezes, não há limites de tempo, mas ainda consigo alguns por hora. O erro vem de qualquer um dos métodos invocados. Um desses métodos não possui parâmetros e retorna alguns dados. Outro recebe muitos dados como parâmetro, mas executa de forma assíncrona. Os erros sempre se originam do cliente e nunca fazem referência a nenhum código no servidor no rastreamento da pilha. Sempre termina com:
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
No servidor: Tentei (e atualmente tenho) as seguintes configurações de ligação:
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"
Não parece ter impacto.
Eu tentei (e atualmente tenho) as seguintes configurações de limitação:
<serviceThrottling maxConcurrentCalls="1500" maxConcurrentInstances="1500" maxConcurrentSessions="1500"/>
Não parece ter impacto.
Atualmente, tenho as seguintes configurações para o serviço WCF.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
Eu corri com ConcurrencyMode.Multiple
um pouco e o erro ainda ocorreu.
Tentei reiniciar o IIS, reiniciar meu SQL Server subjacente, reiniciar a máquina. Tudo isso parece não ter impacto.
Tentei desativar o firewall do Windows. Não parece ter impacto.
No cliente, tenho estas configurações:
maxReceivedMessageSize="2147483647"
<system.net>
<connectionManagement>
<add address="*" maxconnection="16"/>
</connectionManagement>
</system.net>
Meu cliente fecha suas conexões:
var client = new MyClient();
try
{
return client.GetConfigurationOptions();
}
finally
{
client.Close();
}
Mudei as configurações do registro para permitir mais conexões de saída:
MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.
Tentei recentemente o SvcTraceViewer.exe. Consegui pegar uma exceção no lado do cliente. Vejo que sua duração é de 1 minuto. Olhando para o rastreamento do lado do servidor, posso ver que o servidor não está ciente dessa exceção. A duração máxima que consigo ver é de 10 segundos.
Eu olhei para conexões de banco de dados ativas usando exec sp_who
no servidor. Eu só tenho alguns (2-3). Eu olhei para conexões TCP de um cliente usando TCPview. Geralmente é cerca de 2-3 e eu vi até 5 ou 6.
Simplificando, estou perplexo. Tentei tudo o que pude encontrar e deve estar faltando algo muito simples que um especialista WCF seria capaz de ver. Tenho a sensação de que algo está bloqueando meus clientes no baixo nível (TCP), antes que o servidor realmente receba a mensagem e / ou que algo está enfileirando as mensagens no nível do servidor e nunca permitindo que sejam processadas.
Se você tiver quaisquer contadores de desempenho que eu deva examinar, entre em contato. (indique quais valores são ruins, pois alguns desses contadores são difíceis de decifrar). Além disso, como posso registrar o tamanho da mensagem WCF? Finalmente, existem ferramentas disponíveis que me permitiriam testar quantas conexões posso estabelecer entre meu cliente e servidor (independentemente de meu aplicativo)
Obrigado pelo seu tempo!
Informações extras adicionadas em 20 de junho:
Meu aplicativo WCF faz algo semelhante ao seguinte.
while (true)
{
Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
Step2GetWorkUnitFromServerViaWCF();
DoWorkLocally(); // takes 5-15minutes.
Step3SendBackResultsToServerViaWCF();
}
Usando o WireShark, vi que, quando o erro ocorre, tenho cinco retransmissões de TCP seguidas por uma redefinição de TCP posteriormente. Meu palpite é que o RST está vindo do WCF interrompendo a conexão. O relatório de exceção que recebo é do tempo limite da Etapa 3.
Eu descobri isso olhando para o fluxo tcp "tcp.stream eq 192". Em seguida, expandi meu filtro para "tcp.stream eq 192 e http e http.request.method eq POST" e vi 6 POSTs durante esse fluxo. Isso parecia estranho, então verifiquei com outro stream, como tcp.stream eq 100. Tive três POSTs, o que parece um pouco mais normal porque estou fazendo três chamadas. No entanto, eu fecho minha conexão após cada chamada do WCF, então eu esperava uma chamada por fluxo (mas não sei muito sobre TCP).
Investigando um pouco mais, eu despejei a carga do pacote http no disco para ver o que essas seis chamadas eram.
1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2
Meu palpite é que dois clientes simultâneos estão usando a mesma conexão, por isso vi duplicatas. No entanto, ainda tenho mais alguns problemas que não consigo compreender:
a) Por que o pacote está corrompido? Acaso aleatório da rede - talvez? A carga é compactada usando este código de amostra: http://msdn.microsoft.com/en-us/library/ms751458.aspx - O código pode apresentar erros de vez em quando quando usado simultaneamente? Devo testar sem a biblioteca gzip.
b) Por que eu veria as etapas 1 e 2 em execução APÓS o tempo limite da operação corrompida expirar? Parece-me que essas operações não deveriam ter ocorrido. Talvez eu não esteja olhando para o fluxo certo porque minha compreensão do TCP é falha. Tenho outros streams que ocorrem ao mesmo tempo. Devo investigar outros fluxos - uma rápida olhada nos fluxos 190-194 mostra que o POST do Step3 tem dados de carga útil adequados (não corrompidos). Me empurrando para olhar para a biblioteca gzip novamente.