Abbiamo un'applicazione che ha un servizio WCF (* .svc) in esecuzione su IIS7 e vari client che interrogano il servizio. Il server esegue Win 2008 Server. I client eseguono Windows 2008 Server o Windows 2003 Server. Ricevo la seguente eccezione, che ho visto può in effetti essere correlata a un gran numero di potenziali problemi di 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.
Ho aumentato il timeout a 30 minuti e l'errore si è verificato ancora. Questo mi dice che qualcos'altro è in gioco, perché la quantità di dati non potrebbe richiedere 30 minuti per essere caricata o scaricata.
L'errore va e viene. Al momento è più frequente. Non sembra avere importanza se ho 3 client in esecuzione contemporaneamente o 100, si verifica ancora una volta ogni tanto. La maggior parte delle volte non ci sono timeout ma ne ricevo comunque alcuni ogni ora. L'errore proviene da uno dei metodi richiamati. Uno di questi metodi non ha parametri e restituisce un po 'di dati. Un altro accetta molti dati come parametro ma viene eseguito in modo asincrono. Gli errori provengono sempre dal client e non fanno mai riferimento a alcun codice sul server nell'analisi dello stack. Finisce sempre con:
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Sul server: ho provato (e attualmente ho) le seguenti impostazioni di associazione:
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"
Non sembra avere un impatto.
Ho provato (e attualmente ho) le seguenti impostazioni di limitazione:
<serviceThrottling maxConcurrentCalls="1500" maxConcurrentInstances="1500" maxConcurrentSessions="1500"/>
Non sembra avere un impatto.
Al momento ho le seguenti impostazioni per il servizio WCF.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
Ho funzionato con ConcurrencyMode.Multiple
per un po 'e l'errore si è verificato ancora.
Ho provato a riavviare IIS, riavviare il mio SQL Server sottostante, riavviare la macchina. Tutti questi non sembrano avere un impatto.
Ho provato a disabilitare il firewall di Windows. Non sembra avere un impatto.
Sul client, ho queste impostazioni:
maxReceivedMessageSize="2147483647"
<system.net>
<connectionManagement>
<add address="*" maxconnection="16"/>
</connectionManagement>
</system.net>
Il mio cliente chiude le sue connessioni:
var client = new MyClient();
try
{
return client.GetConfigurationOptions();
}
finally
{
client.Close();
}
Ho modificato le impostazioni del registro per consentire più connessioni in uscita:
MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.
Ora ho provato di recente SvcTraceViewer.exe. Sono riuscito a catturare un'eccezione sul lato client. Vedo che la sua durata è di 1 minuto. Guardando la traccia lato server, posso vedere che il server non è a conoscenza di questa eccezione. La durata massima che posso vedere è di 10 secondi.
Ho esaminato le connessioni al database attive utilizzando exec sp_who
sul server. Ne ho solo pochi (2-3). Ho esaminato le connessioni TCP da un client utilizzando TCPview. Di solito è intorno a 2-3 e ne ho visti fino a 5 o 6.
In poche parole, sono perplesso. Ho provato tutto ciò che sono riuscito a trovare e deve mancare qualcosa di molto semplice che un esperto WCF sarebbe in grado di vedere. Ho la sensazione viscerale che qualcosa stia bloccando i miei client a basso livello (TCP), prima che il server riceva effettivamente il messaggio e / o che qualcosa stia accodando i messaggi a livello di server e non lasciandoli mai elaborare.
Se dovrei esaminare dei contatori delle prestazioni, fatemelo sapere. (si prega di indicare quali valori sono negativi, poiché alcuni di questi contatori sono difficili da decifrare). Inoltre, come posso registrare la dimensione del messaggio WCF? Infine, ci sono strumenti che mi permettano di testare quante connessioni posso stabilire tra il mio client e il server (indipendentemente dalla mia applicazione)
Grazie per il tuo tempo!
Ulteriori informazioni aggiunte il 20 giugno:
La mia applicazione WCF fa qualcosa di simile al seguente.
while (true)
{
Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
Step2GetWorkUnitFromServerViaWCF();
DoWorkLocally(); // takes 5-15minutes.
Step3SendBackResultsToServerViaWCF();
}
Utilizzando WireShark, ho visto che quando si verifica l'errore, ho cinque ritrasmissioni TCP seguite da un ripristino TCP in seguito. La mia ipotesi è che l'RST provenga da WCF che interrompe la connessione. Il rapporto di eccezione che ricevo proviene dal timeout del passaggio 3.
L'ho scoperto guardando il flusso tcp "tcp.stream eq 192". Ho quindi esteso il mio filtro a "tcp.stream eq 192 e http e http.request.method eq POST" e ho visto 6 POST durante questo flusso. Sembrava strano, quindi ho controllato con un altro stream come tcp.stream eq 100. Avevo tre POST, il che sembra un po 'più normale perché sto facendo tre chiamate. Tuttavia, chiudo la connessione dopo ogni chiamata WCF, quindi mi sarei aspettato una chiamata per flusso (ma non so molto di TCP).
Indagando un po 'di più, ho scaricato il carico del pacchetto http su disco per vedere cosa queste sei chiamate dove.
1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2
La mia ipotesi è che due client simultanei stiano utilizzando la stessa connessione, ecco perché ho visto i duplicati. Tuttavia, ho ancora alcuni altri problemi che non riesco a comprendere:
a) Perché il pacchetto è danneggiato? Un colpo di fortuna di rete casuale - forse? Il carico viene compresso con gzip utilizzando questo codice di esempio: http://msdn.microsoft.com/en-us/library/ms751458.aspx - Il codice potrebbe essere difettoso una volta ogni tanto se usato contemporaneamente? Dovrei provare senza la libreria gzip.
b) Perché dovrei vedere i passaggi 1 e 2 in esecuzione DOPO il timeout dell'operazione danneggiata? Mi sembra che queste operazioni non sarebbero dovute avvenire. Forse non sto guardando il flusso giusto perché la mia comprensione del TCP è errata. Ho altri flussi che si verificano contemporaneamente. Dovrei indagare su altri flussi: una rapida occhiata ai flussi 190-194 mostra che il POST Step3 ha dati di carico utili adeguati (non danneggiati). Spingendomi a guardare di nuovo la libreria gzip.