Nous avons une application qui a un service WCF (*.svc) fonctionnant sur IIS7 et plusieurs clients qui interrogent le service. Le serveur fonctionne sous Win 2008 Server. Les clients utilisent soit Windows 2008 Server, soit Windows 2003 Server. J'obtiens l'exception suivante, dont j'ai constaté qu'elle peut en fait être liée à un grand nombre de problèmes WCF potentiels.
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.
J'ai augmenté le délai d'attente à 30 minutes et l'erreur est toujours présente. Cela m'indique que quelque chose d'autre est en jeu, car la quantité de données ne pourrait jamais prendre 30 minutes à charger ou à télécharger.
L'erreur va et vient. En ce moment, elle est plus fréquente. Peu importe que j'aie 3 clients en cours d'exécution simultanément ou 100, elle se produit toujours de temps en temps. La plupart du temps, il n'y a pas de délais d'attente, mais j'en ai quand même quelques-uns par heure. L'erreur provient de l'une des méthodes invoquées. L'une de ces méthodes n'a pas de paramètres et renvoie un peu de données. Une autre prend beaucoup de données en paramètre mais s'exécute de manière asynchrone. Les erreurs proviennent toujours du client et ne font jamais référence à un quelconque code sur le serveur dans la trace de la pile. Elle se termine toujours par :
at System.Net.HttpWebRequest.GetResponse()
at System.ServiceModel.Channels.HttpChannelFactory.HttpRequestChannel.HttpChannelRequest.WaitForReply(TimeSpan timeout)
Sur le serveur : J'ai essayé (et j'ai actuellement) les paramètres de liaison suivants :
maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"
Il ne semble pas avoir d'impact.
J'ai essayé (et j'ai actuellement) les paramètres d'étranglement suivants :
<serviceThrottling maxConcurrentCalls="1500" maxConcurrentInstances="1500" maxConcurrentSessions="1500"/>
Il ne semble pas avoir d'impact.
J'ai actuellement les paramètres suivants pour le service WCF.
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]
J'ai couru avec ConcurrencyMode.Multiple
pendant un moment, et l'erreur se produisait toujours.
J'ai essayé de redémarrer IIS, de redémarrer mon serveur SQL sous-jacent, de redémarrer la machine. Toutes ces tentatives ne semblent pas avoir d'impact.
J'ai essayé de désactiver le pare-feu de Windows. Cela ne semble pas avoir d'impact.
Sur le client, j'ai ces paramètres :
maxReceivedMessageSize="2147483647"
<system.net>
<connectionManagement>
<add address="*" maxconnection="16"/>
</connectionManagement>
</system.net>
Mon client ferme ses connexions :
var client = new MyClient();
try
{
return client.GetConfigurationOptions();
}
finally
{
client.Close();
}
J'ai modifié les paramètres du registre pour autoriser davantage de connexions sortantes :
MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.
Je viens d'essayer SvcTraceViewer.exe. J'ai réussi à attraper une exception du côté du client. Je vois que sa durée est de 1 minute. En regardant la trace côté serveur, je peux voir que le serveur n'est pas au courant de cette exception. La durée maximale que je peux voir est de 10 secondes.
J'ai examiné les connexions actives à la base de données en utilisant exec sp_who
sur le serveur. Je n'en ai que quelques-uns (2-3). J'ai examiné les connexions TCP d'un client en utilisant TCPview. Elles sont généralement au nombre de 2-3 et j'en ai vu jusqu'à 5 ou 6.
Pour faire simple, je suis dans l'impasse. J'ai essayé tout ce que j'ai pu trouver, et je dois manquer quelque chose de très simple qu'un expert WCF serait capable de voir. J'ai l'impression que quelque chose bloque mes clients au niveau inférieur (TCP), avant que le serveur ne reçoive réellement le message et/ou que quelque chose met les messages en file d'attente au niveau du serveur et ne les laisse jamais se traiter.
Si vous avez des compteurs de performance que je devrais examiner, faites-le moi savoir. (veuillez indiquer quelles valeurs sont mauvaises, car certains de ces compteurs sont difficiles à décrypter). De même, comment pourrais-je enregistrer la taille des messages WCF ? Enfin, existe-t-il des outils qui me permettraient de tester le nombre de connexions que je peux établir entre mon client et mon serveur (indépendamment de mon application) ?
Merci pour votre temps !
Informations supplémentaires ajoutées le 20 juin :
Mon application WCF fait quelque chose de similaire à ce qui suit.
while (true)
{
Step1GetConfigurationSettingsFromServerViaWCF(); // can change between calls
Step2GetWorkUnitFromServerViaWCF();
DoWorkLocally(); // takes 5-15minutes.
Step3SendBackResultsToServerViaWCF();
}
En utilisant WireShark, j'ai vu que lorsque l'erreur se produit, j'ai cinq retransmissions TCP suivies d'une réinitialisation TCP plus tard. Je pense que le RST provient de WCF qui coupe la connexion. Le rapport d'exception que je reçois provient de l'arrêt de l'étape 3.
J'ai découvert cela en regardant le flux tcp "tcp.stream eq 192". J'ai ensuite étendu mon filtre à "tcp.stream eq 192 and http and http.request.method eq POST" et j'ai vu 6 POSTs durant ce flux. Cela semblait étrange, j'ai donc vérifié avec un autre flux tel que tcp.stream eq 100. J'ai eu trois POST, ce qui semble un peu plus normal car je fais trois appels. Cependant, je ferme ma connexion après chaque appel WCF, donc je me serais attendu à un appel par flux (mais je ne connais pas beaucoup le TCP).
En enquêtant un peu plus, j'ai vidé la charge de paquets http sur le disque pour voir à quoi correspondaient ces six appels.
1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2
Je pense que deux clients simultanés utilisent la même connexion, c'est pourquoi j'ai vu des doublons. Cependant, j'ai encore quelques autres problèmes que je n'arrive pas à comprendre :
a) Pourquoi le paquet est-il corrompu ? Un hasard du réseau - peut-être ? Le chargement est gzippé en utilisant cet exemple de code : http://msdn.microsoft.com/en-us/library/ms751458.aspx - Le code pourrait-il être bogué de temps en temps lorsqu'il est utilisé simultanément ? Je devrais tester sans la bibliothèque gzip.
b) Pourquoi l'étape 1 et l'étape 2 s'exécutent-elles APRÈS la fin de l'opération corrompue ? Il me semble que ces opérations n'auraient pas dû avoir lieu. Peut-être que je ne regarde pas le bon flux parce que ma compréhension du TCP est imparfaite. J'ai d'autres flux qui se produisent en même temps. Je devrais examiner d'autres flux - un coup d'œil rapide aux flux 190-194 montre que le POST Step3 a des données utiles correctes (non corrompues). Cela me pousse à regarder à nouveau la bibliothèque gzip.