2009-08-12 7 views
7

J'essaie de consigner ce qui se passe lorsque le client se bloque lors d'un appel de service Web.Comment: service Web et gestion des délais d'expiration des clients dans le service Web?

Jetez un coup d'œil au code HelloWorld ci-dessous. C'est ce que je souhaite faire, mais il semble que IsClientConnected ne fonctionne pas car il retourne toujours vrai.

[WebMethod] 
public string HelloWorld() { 
    //.. Do the Webservice stuff 
    if (!Context.Response.IsClientConnected) { 
     //Log some vital info about this call that timed out... 
    } 
    return "The WebService Result"; 
} 

Est-ce que quelqu'un connaît une autre façon de vérifier l'état de l'appel du service Web?

Lorsque des clients se déconnectent d'un appel de service Web, aucune exception n'est générée dans le service Web. Le code continue de s'exécuter jusqu'à ce qu'il soit fait et renvoie ensuite son résultat dans le néant (lorsque la connexion est fermée).

+3

La version d'IIS joue un grand rôle dans la précision de IsClientConnected. Je suis impatient de voir ce que les autres ont imaginé pour résoudre ce même problème * sans * interroger. – Marc

Répondre

0

Je m'attendrais à ce que chaque appel de service Web soit une demande/réponse. En cas d'erreur telle que l'indisponibilité du service ou les délais, je m'attendrais à une exception.

Alors, est-il possible d'entourer l'appel avec un try try?

+0

Aucune exception n'est générée dans le service Web lorsque le client expire. Il finit juste et "envoie" le résultat dans le néant. – Wolf5

+0

aha, donc vous parlez du côté serveur, pas du côté client. Désolé, ce n'était pas clair pour moi. – djna

-1

Il est préférable de s'abonner à une sorte d'événement que de vérifier un drapeau. Fondamentalement, ASP.NET est en train de tuer la requête car elle prend plus de temps que la valeur de délai d'attente configurée (paramètre executionTimeout dans l'élément httpRuntime). Cependant, je ne suis pas sûr si un tel événement provient de l'environnement d'exécution ASP.NET. Apparemment, il ne soulève aucune exception non plus. Il semble donc y avoir une déconnexion entre votre service et le runtime ASP.NET dans ce cas particulier. Je serais intéressé de savoir s'il y a un moyen/un truc pour accomplir ce que vous recherchez.

En attendant, vous pouvez consulter les compteurs de performance ASP.NET. Il y en a un appelé "Demandes expirées". Cela peut inclure des demandes qui ont expiré pendant l'attente dans une file d'attente ou pendant l'exécution. Vous pouvez lire ce compteur de performance pour votre service Web au début et à la fin de votre méthode Web. Si le nombre a sauté, cela signifie une demande juste un délai. Cela peut ne pas signifier que le saut correspond à cette requête particulière mais dans tous les cas, vous pouvez toujours enregistrer des informations telles que les paramètres passés à la méthode web, le temps écoulé, etc. Vous pouvez également augmenter la valeur de executionTimeout dans web.config pour permettre plus de temps pendant que vous essayez d'optimiser votre méthode Web pour qu'elle s'exécute plus rapidement si vos clients ont besoin d'une solution immédiate.

S'il s'agit d'un service Web asmx, vous pouvez examiner l'événement Session_End dans global.asax. Il peut être appelé lorsque ASP.NET supprime la demande.

Juste quelques pensées.

+1

-1: Qu'est-ce qui vous fait penser que la requête est "tuée"? Tout ce qu'il sait, c'est que le client obtient un délai d'attente. –

+0

Qu'est-ce qui vous fait penser qu'il n'est pas? Peut-être que vous devriez commencer à vous concentrer davantage sur la fourniture de réponses que d'essayer de trouver des failles avec les messages d'autres personnes. Nous essayons de donner des directions et des conseils à OP. À la fin, il doit décider lequel est applicable ou le meilleur pour son problème. Nous avons seulement des informations limitées à travailler avec et faire des hypothèses contre. –

+1

"he"? Il suppose que le service sera averti si le client se "déconnecte". Ce n'est pas le cas. Il suppose également que le client se déconnecte. Tout cela est déduit du fait que le client expire. Le fait est que tout ce que nous savons, c'est que le client expire. –

0

Cela dépendra des détails de l'infrastructure de service Web que vous utilisez. D'après ce que vous montrez, je ne serais pas surpris si vous n'aviez aucun mécanisme pour le détecter.

Considérons qu'en général, un service Web ne doit même pas utiliser un transport tel que HTTP, vous pouvez répondre via des files d'attente, ou même par e-mail. En général, vous ne pouvez pas, en tant que serveur, mettre en œuvre un simple service Web, assurez-vous que votre client a vu la réponse. Que voulez-vous déduire si votre test a fonctionné? Au moment où vous avez fait le test, il est là, une nanoseconde après que vous ayez décidé de ne pas vous connecter, mais avant votre retour, il est parti. Il n'y a pas de relation transactionnelle entre Client et Serveur en SOAP/HTTP simple.

Il existe des normes de service Web supplémentaires pour résoudre certains de ces problèmes, mais vous devez généralement concevoir vos services Web en supposant que l'appelant ne puisse pas voir la réponse. (peut-être que vous fournissez également des services de statut, de sorte qu'un client peut déposer et ensuite revenir et demander «avez-vous traité l'ordre» 345 »).

S'il vous plaît dites-nous ce que vous voulez réaliser avec cette journalisation, peut-être que quelqu'un a une approche de conception pour vous aider.

+0

Problèmes avec un service dans un cluster, mais nous ne savons pas quels sont les services de cluster qui arrivent à expiration lorsque les clients se connectent à l'URL du cluster et non à l'URL du serveur physique. L'objectif ici est d'ajouter généralement à mes services Web un événement de connexion aux fenêtres dans les cas où il y a un délai d'attente ou une déconnexion prématurée entre le client et ce serveur. – Wolf5

+0

Je le fais en supposant ce qui suit: Lorsque le client fait un appel WS au serveur, une connexion socket TCP est établie. Cette connexion reste en attente de réponse. Une fois que le service a terminé son code, les données sont renvoyées sur cette connexion. Tant qu'il y a une connexion établie restant active tant que le service fait son code, il devrait y avoir un moyen d'obtenir l'état de cette connexion TCP. – Wolf5

+0

Donc, je veux juste un enregistreur de "basculement" générique pour tous les types de services Web où le client se déconnecte que je peux facilement ajouter dans le code. – Wolf5

0

Le protocole HTTP n'a aucune spécification sur la façon dont le serveur peut exécuter un ping sur le client. Le sens de IsClientConnected - pour vérifier s'il existe une requête "insatisfait" pour rendre HttpResponse. Et peut-être (je ne suis pas sûr) si le client supporte keep-connection-alive. Pensez à tirer l'architecture - vous aviez une méthode unidirectionnelle, et un chien de garde du côté client pour vérifier périodiquement si la méthode est faite.

+0

True. Cela échouera sur une solution d'interrogation, mais jusqu'à présent, lorsque j'ai détecté le trafic réseau concernant les services Web, il y a une demande et une réponse. Il n'y avait jamais une nouvelle connexion HTTP établie pour recevoir le résultat, car cela se montrerait dans un nouvel entête HTTP au serveur. Donc, je suppose qu'il y a un lien maintenu en vie. Cette connexion sera un socket .Net d'une certaine manière. Probablement caché, mais le pire des cas accessible par un petit reflet. Les prises ont un état que je peux vérifier. – Wolf5

+0

Oui, vous avez raison. IsClientConnected renvoie exactement ce que vous décrivez. Keep-alive est juste un drapeau d'optiomisation, mais pas la règle. C'est pourquoi il est question de possibilité (! Seulement) de transférer autre chose sur le même socket. – Dewfy

0

Je pense que pour que IsClientConnected renvoie false, la partie de votre code de service Web qui dit «// .. Do the Webservice stuff» devrait être plus longue à exécuter que le paramètre de délai d'attente du client. Vous pouvez probablement simuler cela en définissant le délai d'expiration du client sur 60 secondes et en ajoutant Thread.Sleep (70000) dans votre code de service Web avant l'appel IsClientConnected.

Cependant, je ne pense pas que cela aboutirait à ce que IsClientConnected renvoie false. La temporisation d'une demande de service Web et la réinitialisation de la connexion au serveur sont deux bêtes différentes. Si Response avait une méthode appelée IsClientStillWaitingForThisWebServiceCallToReturn, cela pourrait faire ce que vous voulez.

Je pense que vous pouvez obtenir IsClientConnected pour renvoyer false si vous avez déconnecté physiquement le client du réseau alors que la méthode de service Web était encore dans la partie avant la vérification IsClientConnected, mais je suppose que ce n'est pas ce que vous voulez.

+0

Mes tests de concepts sont juste une application webservice qui exécute un sleep comme vous l'avez mentionné et une autre application qui appelle ce webservice avec un timeout de 100ms. L'application se termine par une erreur = la connexion est fermée. Ensuite, l'application arrive à l'IsClientConnected qui est toujours vrai et renvoie les sorties sans erreurs. – Wolf5

+0

Comme je l'ai dit, le client arrivant à expiration sur une demande de service Web et le client réinitialisant la connexion au serveur ne sont pas la même chose, donc votre résultat ici est exactement ce à quoi je m'attendrais.IsClientConnected renvoie True car le client est toujours connecté au serveur (même si l'appel du service Web a expiré). – MusiGenesis

+1

La temporisation d'un appel de service Web est quelque chose qui se produit uniquement du côté client, et le serveur ne sait rien à ce sujet. – MusiGenesis

1

Je ne crois pas qu'il y aura une exception en général. Même si le service renvoyait une réponse longue, telle que la fenêtre de transmission sortante se fermait et expirait en attendant d'être en mesure d'envoyer des octets, tout cela se produirait après que la méthode Web était revenue à ASP.NET.

Ce que vous devez faire est d'apprendre quelles méthodes Web prennent trop de temps. Vous pouvez commencer à le faire en activant le suivi, comme indiqué dans "Enabling Tracing in ASP.NET Web Services". Vous devrez peut-être aller plus loin et profiler le service pour voir où le temps est passé.

Vous devriez également regarder attentivement les journaux d'événements. Recherchez en particulier les événements d'avertissement provenant de la source d'événement "ASP.NET". Ceux-ci viennent de ASP.NET Health Monitoring. Je vous recommande de vous familiariser avec le système de surveillance de la santé, car vous constaterez qu'il fait beaucoup de choses que vous auriez à écrire vous-même, simplement au prix de la configuration.

+0

Je vais regarder dans le suivi de la santé. J'ai peur que Tracing ne soit mortel. Il y a beaucoup de trafic vers ces services provenant de différents types de clients. A défaut, il ne semble pas y avoir moyen de détecter les déconnexions entre un client et un service Web du côté du service web. S'il y en a, j'espère que quelqu'un éclairera ce fil. – Wolf5

+0

Quelle version du système d'exploitation utilisez-vous? Vista et Server 2008 ont un EtwTraceListener qui se connecte au sous-système "Event Tracing for Windows", ce qui est assez rapide pour que les pilotes de périphériques l'utilisent. –

+0

2003 sur les serveurs. – Wolf5

0

J'ai créé un client de test simple et tournai ma demande de délai d'attente dans 100ms

 HttpWebRequest MakeRequest = (HttpWebRequest)WebRequest.Create("http://localhost:55959/ScanServer.asmx"); 
     if (MakeRequest == null) 
     { 
      throw new Exception(); 
     } 
     HttpWebResponse PostResponse = null; 

     MakeRequest.Method = "POST"; 
     MakeRequest.AuthenticationLevel = System.Net.Security.AuthenticationLevel.None; 
     MakeRequest.UserAgent = "testing"; 
     MakeRequest.Timeout = 100; 
     MakeRequest.ContentType = "application/soap+xml; charset=utf-8;"; 

     try 
     { 
      byte[] PostBytes = UTF8Encoding.UTF8.GetBytes(PostData); 
      MakeRequest.ContentLength = PostBytes.Length; 

      Stream RequestStream = MakeRequest.GetRequestStream(); 
      RequestStream.Write(PostBytes, 0, PostBytes.Length); 

      PostResponse = (HttpWebResponse)MakeRequest.GetResponse(); 
     } 
     catch 
     { 
      throw; 
     } 

l'intérieur d'un appel WebService SOAP lors du débogage j'ai attendu sur un point de rupture jusqu'à ce que le client a reçu l'exception du délai d'attente. La valeur Context.Response.IsClientConnected a ensuite été définie sur false. J'ai également utilisé Fiddler pour envoyer une requête et quand au point de rupture du serveur j'ai interrompu la session. Encore une fois, la valeur a été définie sur false. Je n'arrive pas à comprendre pourquoi vous voyez un timeout sans pouvoir enregistrer les données lors de la vérification de IsClientConnected sauf si le timeout est dans la connexion initiale à votre serveur.

Questions connexes