Enquête détaillée sur l'exception relative au délai d'attente de la WCF

Nous avons une application qui a un service WCF (*.svc) fonctionnant sur IIS7 et divers clients demandant le service. Le serveur exécute Win 2008 Server. Les clients utilisent Windows 2008 Server ou Windows 2003 server. Je suis l'exception suivante, que j'ai vu peut en effet être liée à un grand nombre de WCF questions.

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 temps d'arrêt à 30min et l'erreur s'est encore produite. Cela me dit que quelque chose d'autre est en jeu, parce que la quantité de données ne pourrait jamais prendre 30min pour télécharger ou télécharger.

l'erreur va et vient. À l'heure actuelle, elle est plus fréquente. Cela ne semble pas avoir d'importance si j'ai 3 clients qui fonctionnent simultanément ou 100, cela se produit encore une fois de temps en temps. La plupart du temps, il n'y a pas de temps mort, mais j'en ai encore quelques-uns par heure. L'erreur provient de l'une des méthodes qui sont appelées. L'une de ces méthodes n'a pas de paramètres et retourne un peu de données. Un autre prend beaucoup de données comme paramètre mais exécute asynchrone. Les erreurs proviennent toujours du client et ne font jamais référence à aucun 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 actuellement) les paramètres de liaison:

maxBufferSize="2147483647" maxReceivedMessageSize="2147483647" maxBufferPoolSize="2147483647"

il ne semble pas avoir d'impact.

j'ai essayé (et actuellement) suivantes réglages de l'accélérateur:

<serviceThrottling maxConcurrentCalls="1500"   maxConcurrentInstances="1500"    maxConcurrentSessions="1500"/>

il ne semble pas avoir d'impact.

j'ai actuellement les réglages suivants pour le service WCF.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode = ConcurrencyMode.Single)]

j'ai couru avec ConcurrencyMode.Multiple pendant un certain temps, et l'erreur s'est produite.

j'ai essayé de redémarrer IIS, redémarrer mon serveur SQL sous-jacent, redémarrer la machine. Tout cela ne semble pas avoir d'impact.

J'ai essayé de désactiver le pare-feu Windows. Il ne semble pas avoir un 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 permettre plus de connexions sortantes:

MaxConnectionsPerServer=24, MaxConnectionsPer1_0Server=32.

je viens d'essayer SvcTraceViewer.EXE. J'ai réussi à attraper une exception du côté des clients. Je vois que sa durée est d'une minute. En regardant la trace côté serveur, je peux voir que le serveur n'est pas conscient de cette exception. La durée maximale que je peux voir est de 10 secondes.

j'ai regardé les connexions de base de données actives en utilisant exec sp_who sur le serveur. Je n'ai que quelques (2-3). J'ai examiné les connexions TCP d'un client en utilisant TCPview. Il est généralement autour de 2-3 et j'ai vu jusqu'à 5 ou 6.

simplement dit, je suis perplexe. J'ai essayé tout ce que j'ai pu trouver, et je dois rater quelque chose de très simple qu'un expert de la WCF pourrait voir. J'ai l'impression que quelque chose bloque mes clients au bas niveau (TCP), avant que le serveur ne reçoive réellement le message et/ou que quelque chose fait la queue au niveau du serveur et ne les laisse jamais traiter.

si vous avez des compteurs de performances que je devrais regarder, s'il vous plaît faites le moi savoir. (veuillez indiquer les valeurs qui sont mauvaises, car certaines d'entre elles les compteurs sont difficiles à déchiffrer). En outre, comment pourrais-je enregistrer la taille du message WCF? Enfin, y a-t-il des outils là-bas qui me permettraient de tester combien de connexions je peux établir entre mon client et le serveur (indépendamment de mon application)

Merci pour votre temps!

information supplémentaire ajoutée 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();
}

à l'Aide de WireShark, j'ai vu que lorsque l'erreur se produit, j'ai cinq retransmissions TCP suivies d'une réinitialisation TCP plus tard. À mon avis, Le RST vient de la WCF, tuant la connexion. Le rapport d'exception que je reçois vient de L'Étape 3.

j'ai découvert en regardant le flux tcp tcp.flux eq 192". J'ai ensuite étendu mon filtre à "tcp.flux eq 192 et http et http.demande.méthode eq POST" et a vu 6 postes au cours de ce flux. Cela semblait étrange, donc j'ai vérifié avec un autre flux tel que tcp.flux eq 100. J'ai eu trois messages, ce qui semble un peu plus normal parce que je fais trois appels. Cependant, je ferme ma connexion après chaque appel WCF, donc je m'attendais à un appel par flux (mais je ne sais pas grand chose sur TCP).

en enquêtant un peu plus, j'ai jeté la charge du paquet http sur le disque pour regarder ce que ces six appels appellent où.

1) Step3
2) Step1
3) Step2
4) Step3 - corrupted
5) Step1
6) Step2

à mon avis, deux clients concurrents utilisent le même connexion, c'est pourquoi j'ai vu des doublons. Cependant, j'ai encore quelques questions que je ne comprends pas:

a) Pourquoi le paquet est-il corrompu? Réseau aléatoire fluke - peut-être? La charge est compressée en utilisant ce code d'échantillon: http://msdn.microsoft.com/en-us/library/ms751458.aspx - le code peut-il être altéré de temps en temps lorsqu'il est utilisé simultanément? Je devrais tester sans la bibliothèque gzip.

B) pourquoi verrais-je les étapes 1 et 2 courir après l'opération corrompue chronométrée? Il me semble que ces opérations n'auraient pas dû avoir lieu. Peut-être que je ne suis pas à la recherche de la bonne voie parce que ma compréhension de TCP est défectueuse. J'ai d'autres courants qui se produisent en même temps. Je devrais examiner d'autres flux - un coup d'oeil rapide sur les flux 190-194 montrer que le post Step3 ont des données de charge utile appropriées (non corrompu). Me poussant à revoir la bibliothèque gzip.

92
demandé sur Kent Boogaart 2009-06-11 18:35:07

12 réponses

si vous utilisez le client. Net alors vous n'avez peut-être pas défini

//This says how many outgoing connection you can make to a single endpoint. Default Value is 2
System.Net.ServicePointManager.DefaultConnectionLimit = 200;

voici la question et la réponse originale WCF Service Throttling

mise à Jour :

cette config va dans l'application client .Net peut être au démarrage ou n'importe quand mais avant de commencer vos tests.

de plus, vous pouvez l'avoir dans app.fichier de configuration comme suit

<system.net>
    <connectionManagement>
      <add maxconnection = "200" address ="*" />
    </connectionManagement>
  </system.net>
47
répondu Mubashar Ahmad 2017-05-23 12:17:21

si vous ne l'avez pas déjà essayé - encapsulez vos opérations WCF côté serveur dans les blocs try/finally, et ajoutez la journalisation pour vous assurer qu'elles reviennent réellement.

si ceux-ci montrent que les opérations sont terminées, alors ma prochaine étape serait d'aller à un niveau inférieur, et de regarder la couche de transport réelle.

Wireshark ou un autre outil similaire de capture de paquets peut être très utile à ce stade. Je suppose que cela fonctionne sur HTTP sur le port standard 80.

Lancez Wireshark sur le client. Dans les Options lorsque vous démarrez la capture, définissez le filtre de capture à tcp http and host service.example.com - cela réduira la quantité de trafic non pertinent.

si vous le pouvez, modifiez votre client pour vous informer de l'heure exacte du début de l'appel, et de l'heure à laquelle le délai s'est produit. Ou tout simplement de le surveiller de près.

quand vous obtenez une erreur, alors vous pouvez trawl à travers les logs Wireshark pour trouver le début de l'appel. Cliquez avec le bouton droit de la souris sur le premier paquet sur lequel votre client appelle (cela devrait être quelque chose comme GET /service).svc ou Poste /service.svc) et sélectionnez Suivre TCP Stream.

Wireshark décodera toute la Conversation HTTP, de sorte que vous pouvez vous assurer que WCF envoie effectivement des réponses.

3
répondu 2009-06-17 17:05:47

de: http://www.codeproject.com/KB/WCF/WCF_Operation_Timeout_.aspx

pour éviter cette erreur de temporisation, nous avons besoin à configurer le OperationTimeout propriété pour mandataire dans le client WCF code. Cette configuration est quelque chose nouveau contrairement à d'autres configurations telles comme envoyer Timeout, recevoir Timeout etc., dont j'ai parlé au début du article. Pour régler cette opération temps mort propriété configuration, nous devons lancer notre mandataire à IContextChannel dans Application client WCF avant d'appeler le contrat d'opération méthodes.

2
répondu Joel Martinez 2009-06-11 15:22:05

j'ai un problème similaire. Dans le passé, cela a été lié à des problèmes de sérialisation. Si vous rencontrez toujours ce problème, pouvez-vous vérifier que vous pouvez correctement sérialiser les objets sont de retour. Plus précisément, si vous utilisez des objets Linq-to-Sql qui ont des relations, il y a des problèmes connus de sérialisation si vous mettez une référence back sur un objet enfant à l'objet parent et marquez cette référence back comme un DataMember.

vous pouvez vérifiez la sérialisation en écrivant une application de console qui sérialise et désérialise vos objets en utilisant le DataContractSerializer du côté du serveur et quelles que soient les méthodes de sérialisation utilisées par votre client. Par exemple, dans notre application actuelle, nous avons à la fois des clients WPF et Compact Framework. J'ai écrit une application de console pour vérifier que je peux sérialiser en utilisant un DataContractSerializer et deserialiser en utilisant un XmlDesserializer. Vous pourriez essayer ça.

aussi, si vous revenez Linq-to-Sql objets qui ont des collections d'enfants, vous pourriez essayer de s'assurer que vous avez chargé avidement du côté du serveur. Parfois, à cause du chargement paresseux, les objets retournés ne sont pas remplis et peuvent causer le comportement que vous voyez où la requête est envoyée à la méthode de service plusieurs fois.

si vous avez résolu ce problème, j'aimerais entendre comment parce que je suis coincé avec elle aussi. J'ai vérifié que mon problème n'est pas la sérialisation donc je suis à une perte.

mise à jour: Je ne suis pas sûr que cela vous aidera, mais L'outil de suivi de trace de Service vient de résoudre mon problème après 5 jours d'expérience très similaire à la vôtre. En établissant le traçage et en regardant ensuite le XML brut, j'ai trouvé les exceptions qui causaient mes problèmes de sérialisation. Il s'agissait d'objets Linq-to-SQL qui, à l'occasion, avaient plus d'objets enfants que ceux qui pouvaient être sérialisés avec succès. Ajouter ce qui suit à votre site web.fichier de configuration devrait permettre le suivi:

<sharedListeners>
    <add name="sharedListener"
         type="System.Diagnostics.XmlWriterTraceListener"
         initializeData="c:\Temp\servicetrace.svclog" />
  </sharedListeners>
  <sources>
    <source name="System.ServiceModel" switchValue="Verbose, ActivityTracing" >
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
    <source name="System.ServiceModel.MessageLogging" switchValue="Verbose">
      <listeners>
        <add name="sharedListener" />
      </listeners>
    </source>
  </sources>

le fichier résultant peut être ouvert avec le Service Trace Viewer Tool ou tout simplement dans IE pour examiner les résultats.

2
répondu Brett Bim 2009-08-21 21:20:30

est-ce que vous fermez la connexion au service WCF entre les demandes? Si vous ne le faites pas, vous verrez cette heure exacte (éventuellement).

2
répondu aridlehoover 2011-04-04 22:54:13

je viens de résoudre le problème.J'ai trouvé que les noeuds dans L'application.fichier de configuration mal configuré.

<client>
<endpoint name="WCF_QtrwiseSalesService" binding="wsHttpBinding" bindingConfiguration="ws" address="http://cntgbs1131:9005/MyService/TGE.ISupplierClientManager" contract="*">
</endpoint>
</client>

<bindings>
    <wsHttpBinding>
        <binding name="ws" maxBufferPoolSize="2147483647" maxReceivedMessageSize="2147483647" messageEncoding="Text">
            <readerQuotas maxDepth="2147483647" maxStringContentLength="2147483647" maxArrayLength="2147483647" maxBytesPerRead="2147483647" maxNameTableCharCount="2147483647"/>
            <**security mode="None">**
                <transport clientCredentialType="None"></transport>
            </security>
        </binding>
    </wsHttpBinding>
</bindings>

confirmez votre configuration dans le noeud <security> ,l'attribut "mode" valeur est "None". Si votre valeur est "Transport",l'erreur se produit.

2
répondu alexanderlc 2011-11-18 07:35:26

avez-vous essayé d'utiliser clientVia pour voir le message envoyé, en utilisant SOAP toolkit ou quelque chose comme ça? Cela pourrait aider à voir si l'erreur provient du client lui-même ou d'ailleurs.

0
répondu Philippe 2009-06-15 12:27:48

avez-vous vérifié les traces de la WCF? WCF a tendance à avaler les exceptions et à ne renvoyer que la dernière exception, qui est le temps mort que vous obtenez, puisque le point final n'a rien retourné de significatif.

0
répondu Miki Watts 2009-06-16 08:31:50

vous recevrez également cette erreur si vous renvoyez un objet au client qui contient une propriété de type enum qui n'est pas définie par défaut et qu'enum n'a pas de valeur qui correspond à 0. I. e enum MyEnum{ a=1, b=2};

0
répondu tim 2012-11-28 18:06:34

ressemble à ce message d'exception est très générique et peut être reçu pour une variété de raisons. Nous l'avons rencontré lors du déploiement du client sur les machines Windows 8.1. Notre client WCF fonctionne à l'intérieur d'un service windows et recherche continuellement le service WCF. Le service windows fonctionne sous un utilisateur non administrateur. Le problème a été résolu en paramétrant le clientCredentialType à "Windows" dans la configuration WCF pour permettre l'authentification de passer, comme dans le suivant:

      <security mode="None">
        <transport clientCredentialType="Windows" proxyCredentialType="None"
          realm="" />
        <message clientCredentialType="UserName" algorithmSuite="Default" />
      </security>
0
répondu Alexander Liberson 2014-06-13 15:57:24

Je ne suis pas un expert de la WCF mais je me demande si vous ne tombez pas dans une protection DDOS sur IIS. Je sais par expérience que si vous exécutez un tas de connexions simultanées d'un client simple à un serveur à un moment donné le serveur cesse de répondre aux appels comme il soupçonne une attaque DDOS. Il maintiendra également les connexions ouvertes jusqu'à leur temporisation afin de ralentir le client dans ses attaques.

connexion Multiple provenant de machines/IP différentes devrait ne pas être un problème cependant.

il y a plus d'info dans ce message MSDN:

http://msdn.microsoft.com/en-us/library/bb463275.aspx

découvrez les MaxConcurrentSession sproperty.

0
répondu n3wjack 2016-05-13 14:00:53