Comment un serveur WCF informe-t-il un client WCF des changements? (Meilleure solution que le simple sondage, par exemple comète ou long sondage)
voir aussi " WCF de pousser le client à travers pare-feu "
j'ai besoin d'avoir un client WCF qui se connecte à un serveur WCF, puis quand certaines des données change sur le serveur les clients ont besoin de mettre à jour son affichage.
car il est probable qu'il y ait un pare-feu entre les clients et le serveur.
- tous les communications doivent se faire par HTTP
- le serveur ne peut pas faire un appel (physique) sortant au client.
comme j'écris à la fois le client et le serveur, Je n'ai pas besoin de limiter la solution à l'utilisation de soap, etc.
je cherche construit à surport pour " long polling " / " Comet " etc
Merci pour la réponse la plus informative de Drew Marsh sur la façon de mettre en œuvre le long sondage dans WCF. Cependant, je pensais que le principal "argument de vente" de WCF était que vous pouviez faire ce genre de chose juste en configurant les canaux à utiliser dans le fichier de configuration. e.g. je veux un canal qui est logiquement bidirectionnel, mais qui ne capte que physiquement.
5 réponses
Il me semble que vous connaissez déjà la réponse: l'utilisation d'interrogation. :) Donc je suppose que la seule chose qui reste à expliquer est comment vous pourriez être en mesure d'accomplir cela avec WCF et de la manière la plus efficace possible.
Les principes de base:
- tout d'Abord, décidez combien de temps vous voulez que chaque "long sondage". Pour le bien de l'argument je vais choisir 5 minutes de temps d'arrêt.
- côté client reliure, changer le
sendTimeout="00:05:00"
. - tout comme L'utilisation de XmlHttpRequest (XHR) pour les sondages longs, lorsque le temps d'attente se produit effectivement, vous devrez le détecter et réémettre la prochaine requête de sondage. C'est assez facile dans WCF parce qu'il y a une exception spécifique,
TimeoutException
, que vous pouvez attraper pour détecter facilement ce fut le problème par rapport à une autre exception. - selon la façon dont vous hébergez votre service WCF, vous n'oubliez pas de configurer vous-même pour permettre le traitement jusqu'à 5 minutes. D'un point de vue purement WCF, vous voudrez vous assurer que vous mettez le
receiveTimeout="00:05:00"
. Toutefois, si vous êtes d'hébergement à l'intérieur de ASP.NET vous devrez également configurer l'ASP.NET d'exécution à avoir un plus grand délai d'attente qui est fait à l'aide de la<httpRuntime executionTimeout="300" />
( note: les mesures sont en secondes pour cet attribut).
être efficace dans le client
si vous configurez simplement votre client pour appeler le service et les blocs de clients pendant 5 minutes en attendant une réponse, ce n'est pas une utilisation très efficace des ressources du système. Vous pouvez mettre ces appels sur les threads de fond, mais cela va toujours mâcher une ressource de thread alors que l'appel est en cours. La manière la plus efficace de gérer cela est d'utiliser les opérations asynchrones.
si vous créez vos contrats de services à la main, je vous conseille de vérifier out cette section sur MSDN sur OperationContractAttribute.AsyncPattern
pour plus de détails sur la façon d'ajouter une paire de méthodes async BeginXXX
/ EndXXX
pour chacun de vos appels. Cependant, si vous utilisez svcutil
pour générer vos contrats d'opération pour vous, tout ce que vous devez faire pour avoir des méthodes async générées est de passer l'option /async
sur la ligne de commande. Pour plus de détails sur ce sujet, consultez le sujet synchrone et asynchrone sur MSDN .
maintenant que vous allez définir vos opérations asynchrones, le modèle est très semblable à travailler avec XHR. Vous appelez la méthode BeginXXX
à laquelle vous passez un AsyncCallback
délégué . La méthode BeginXXX
vous retournera un IAsyncResult
, que vous pouvez soit garder si vous voulez pouvoir attendre l'opération (dans des scénarios plus avancés) ou ignorer, et alors l'infrastructure de la FMC enverra de manière asynchrone la demande à le serveur et d'attendre une réponse dans les coulisses. Quand une réponse est reçue ou une exception se produit, le rappel que vous avez passé dans la méthode BeginXXX
sera invoqué. À l'intérieur de cette méthode de rappel, vous devez appeler la méthode correspondante EndXXX
en passant par la IAsyncResult
qui vous est remise. Lors de l'appel à la méthode EndXXX
vous devez employer la manipulation d'exception pour faire face à n'importe quel type de défaut logique qui peut avoir eu lieu alors que j'appelle la méthode, mais c'est aussi là que vous pourrez attraper le TimeoutException
dont nous avons parlé plus tôt. En supposant que vous avez eu une bonne réponse, les données seront retournées à partir de l'appel EndXXX
et vous pouvez réagir à ces données de quelque manière que ce soit a du sens.
NOTE: une chose à garder à l'esprit à propos de ce modèle est la nature du filetage. Les callbacks async de WCF seront reçus sur un thread de le managé pool de threads . Si vous prévoyez de mettre à jour L'UI dans une technologie telle que WPF ou WinForms, vous devez vous assurer que vous marshal les appels vers le fil UI en utilisant les méthodes Invoke
ou BeginInvoke
.
être efficace sur le serveur
si nous devons nous inquiéter de l'efficacité dans le client, nous devrions en être doublement ainsi en ce qui concerne le serveur. Évidemment, ce n' le type d'approche augmente la demande du côté du serveur parce qu'une connexion doit rester ouverte et en attente jusqu'à ce qu'il y ait une raison d'envoyer une notification au client. Le défi ici est que vous voulez seulement lier la course à pied WCF avec le traitement de ces clients qui sont réellement envoyé un événement. Tout le reste devrait être endormi, en attendant que l'événement se produise. Heureusement, le même modèle async que nous venons d'utiliser du côté client fonctionne également du côté serveur. Cependant, il est maintenant une différence majeure: maintenant vous doit retourner le IAsyncResult
(et donc un WaitHandle
) de la méthode BeginXXX
que L'exécution WCF attendra d'être signalée avant d'appeler votre méthode EndXXX
.
Vous pas trouver beaucoup de documentation à l'intérieur de MSDN autres que les liens que j'ai déjà fourni plus tôt et, malheureusement, leurs échantillons sur la rédaction d'un asynchrone-service sont moins utiles. Cela dit, Wenlong Dong a écrit un article sur la mise à l'échelle des services de la FMC avec le modèle async il y a quelque temps que je vous recommande fortement de vérifier.
au-delà de cela, je ne peux honnêtement pas donner trop de conseils sur la meilleure façon de mettre en œuvre le modèle asynchrone du côté du serveur pour vous parce que cela dépend entièrement de quel type de source de données vos événements seront en premier lieu. Fichier I / O? Un message de la file d'attente? Un base de données? Un autre logiciel propriétaire avec son propre service de messagerie que vous essayez de fournir une façade sur? Je ne sais pas, mais ils devraient tous offrir leurs propres modèles asynchrones sur lesquels vous pouvez vous appuyer pour rendre votre propre service aussi efficace que possible.
Prescription Mise À Jour
comme cela semble être une réponse populaire, j'ai pensé que je devrais revenir ici et fournir une mise à jour compte tenu des changements récents dans le paysage. À ce point il ya maintenant une bibliothèque .NET appelé SignalR qui fournit cette fonctionnalité exacte et est certainement la façon dont je recommande la mise en œuvre d'une telle communication avec le serveur.
bien que ce ne soit pas la WCF, vous pouvez essayer D'utiliser XMPP pour activer cette fonctionnalité. Il y a un article sur InfoQ à propos des systèmes informatiques et autres. Alors que L'article indique que XMPP ne peut pas être utilisé sur HTTP, vous pouvez quand vous utilisez BOSH .
Il y a des .Bibliothèques NET disponible agsXMPP au nom de l'un.
l'entreprise où je travaille commence à l'utiliser pour pousser les notifications de mise à jour à un la demande d'actualisation des parties de l'interface utilisateur.
Google pour" WCF duplex ". J'ai utilisé ceci avec succès en utilisant netTcpBinding (à travers les continents), mais je ne suis pas sûr sur basicHttpBinding.
cependant, il faut que le serveur rappelle le client. Si le serveur n'est pas autorisé à faire cela, polling peut être votre seule option...
si le serveur pouvait faire une connexion sortante à un bus de service, vous pourriez implorer un type de rappel. De cette façon, le client/serveur n'aurait pas besoin de se connaître l'un l'autre, juste le bus de service de confiance. Voir ."
La WSDualHttpBinding fournit l'
même soutien Protocoles de Service Web
comme le WSHttpBinding, mais pour une utilisation avec
les contrats duplex. WSDualHttpBinding
ne prend en charge que la sécurité SOAP et
nécessite des messages fiables. Ce
liaison nécessite que le client dispose d'un
URI public qui fournit un service de rappel
le point de terminaison pour le service. C'est
fourni par ClientBaseAddress. Un
double binding expose l'adresse IP de
le client vers le service. Client
devrait utiliser la sécurité pour s'assurer qu'il
ne se connecte qu'aux services en lesquels elle a confiance.
vous voudrez regarder dans WSDualHttpBinding
si le serveur ne peut pas appeler le client (et il ne devrait pas normalement), vous devriez demander au client de sonder le serveur comme vous l'avez spécifié. puisque vous avez déjà la fondation WCF en place, il suffit d'ajouter une opération pour cela.