Comment un serveur WCF informer un client WCF sur les changements? (Meilleure solution alors simple, interrogation, par exemple la comète ou longue interrogation)
-
19-09-2019 - |
Question
voir aussi « WCF pousser au client par le biais pare-feu "
Je dois avoir un client WCF qui se connectent à un serveur WCF, puis lorsque certaines des données modifications sur le serveur les clients ont besoin de mise à jour son affichage.
Comme il est susceptible d'être un pare-feu entre les clients et le serveur.
- Toutes les communications doivent être sur HTTP
- Le serveur ne peut pas faire un (physique) appel sortant au client.
Comme je suis en train d'écrire à la fois le client et le serveur, je ne pas besoin de limiter la solution à n'utiliser du savon etc.
Je cherche construit en surport pour " à long de vote" / « Comet » etc
Merci pour la réponse la plus informative de Drew Marsh sur la façon de mettre en œuvre à long sondages dans WCF. Cependant, je pensais que le principal « point de vente » de WCF est que vous pouvez faire ce genre de chose juste en configurant les canaux à utiliser dans le fichier de configuration. Je veux un par exemple canal logique à double sens, mais seulement physiquement entrant.
La solution
Il me semble que vous connaissez déjà la réponse: utiliser l'interrogation longue. :) Je suppose que la seule chose qui reste à expliquer comment vous pourriez être en mesure d'accomplir ceci avec WCF et de la manière la plus efficace possible.
Les bases:
- Tout d'abord, décider combien de temps vous voulez que chaque « long sondage » pour être. Pour l'amour de la discussion, je vais choisir les délais d'attente de 5 minutes.
- Sur le côté client de liaison, changer le
sendTimeout="00:05:00"
. - Tout comme l'utilisation de XMLHttpRequest (XHR) pour une longue interrogation, lorsque le délai d'attente ne se produit effectivement, vous aurez besoin de le détecter et réémettre la prochaine demande de vote. Ceci est assez facile à WCF, car il y a une exception,
TimeoutException
, que vous pouvez attraper facilement détecter ce fut la question par rapport à une autre exception. - Selon la façon dont vous organisez votre service WCF, vous devez vous assurer de vous configurer pour permettre le traitement jusqu'à 5 minutes. Du point de vue pur WCF vous voulez vous assurer que vous définissez la
receiveTimeout="00:05:00"
. Cependant, si vous hébergez à l'intérieur d'ASP.NET vous devrez également configurer le runtime ASP.NET pour avoir un délai d'attente plus élevé qui est fait en utilisant la<httpRuntime executionTimeout="300" />
( Note: les mesures sont en secondes cet attribut).
Être efficace dans le client
Si vous venez de configurer votre client pour appeler le service de manière synchrone et les blocs clients pour 5 minutes en attendant une réponse, ce n'est pas une utilisation très efficace des ressources du système. Vous pouvez placer ces appels sur les sujets de fond, mais qui va encore à mâcher une ressource de fil alors que l'appel est en cours. La façon la plus efficace pour traiter ce problème est d'utiliser des opérations asynchrones.
Si vous créez vos contrats de service à la main, je vous suggère de vérifier cette section sur MSDN sur OperationContractAttribute.AsyncPattern
pour plus de détails sur la façon d'ajouter une paire de méthode async BeginXXX
/ EndXXX
pour chacun de vos appels. Toutefois, si vous utilisez svcutil
pour générer vos contrats d'exploitation 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, vérifier le sujet synchrone et asynchrone sur MSDN .
Maintenant que vous avez vos opérations vont async définir, le modèle est très semblable à travailler avec XHR. Vous appelez la méthode BeginXXX
auquel vous passez un délégué de AsyncCallback
. La méthode BeginXXX
vous renvoie un IAsyncResult
, que vous pouvez tenir sur si vous voulez être en mesure d'attendre sur le fonctionnement (dans des scénarios plus avancés) ou d'ignorer, et l'infrastructure WCF de manière asynchrone envoyer la demande au serveur et attendre une réponse dans les coulisses. Lorsqu'une réponse est reçue ou une exception se produit, la fonction de rappel que vous avez passé dans la méthode BeginXXX
sera appelée. A l'intérieur de cette méthode de rappel que vous devez appeler la méthode correspondante EndXXX
passant dans le IAsyncResult
qui vous est remis. Au cours de l'appel à la méthode de EndXXX
vous devez utiliser la gestion des exceptions pour faire face à tout type de faute logique qui aurait pu se produire tout en appelant la méthode, mais cela est aussi là que vous souhaitez maintenant être en mesure d'attraper le TimeoutException
dont nous avons parlé plus tôt. En supposant que vous avez obtenu une bonne réponse, les données seront les revenus de la EndXXX
appelez et vous pouvez réagir à ces données de quelque manière logique.
Remarque: Une chose à garder à l'esprit à propos de ce modèle est la nature du filetage. Les callbacks de WCF async seront reçus sur un fil de le pool de threads géré . Si vous envisagez de mettre à jour l'interface utilisateur dans une technologie telle que WPF ou WinForms, vous devez vous assurer que vous maréchal appels vers le thread d'interface utilisateur en utilisant la Invoke
ou BeginInvoke
méthodes .
être efficace sur le serveur
Si nous allons être inquiet sur l'efficacité dans le client, nous devrions être doublement en ce qui concerne le serveur. Il est évident que ce type d'approche met plus la demande sur le côté serveur car une connexion doit rester ouverte et dans l'attente jusqu'à ce qu'il y ait une raison d'envoyer une notification au client. Le défi ici est que vous voulez seulement attacher le moteur d'exécution WCF avec le traitement de ces clients qui sont en fait envoyés un événement. Tout le reste doit juste être endormi, en attendant que l'événement se produise. Heureusement, le même modèle async nous avons juste utilisé sur le côté client travaille également sur le côté des serveurs. Cependant, il y a maintenant une différence majeure: maintenant doit retourner le IAsyncResult
(et donc un Wenlong Dong a écrit une pièce sur l'extension des services WCF avec le modèle async il y a quelque temps que je vous recommande fortement du départ.
Au-delà de cela, je honnêtement, je ne peux pas donner trop de conseils sur la meilleure façon de mettre en œuvre le modèle asynchrone sur le côté serveur pour vous bcause cela dépend entièrement de ce type de source de données vos événements vont venir d'en premier lieu . E / S de fichier? Une file d'attente de messages? Une base de données? Certains autres logiciels propriétaires avec son propre service de messagerie que vous essayez de fournir une façade sur? Je ne sais pas, mais ils devraient tous offrir un modèle async de leur propre sur lequel vous pouvez ferroutage votre propre service pour le rendre aussi efficace que possible.
PrescriptionMise à jour
Comme cela semble être une réponse populaire, je me suis dit que je devrais revenir ici et de fournir une mise à jour compte tenu des récents changements dans le paysage. À ce stade, il y a maintenant une bibliothèque .NET SignalR qui offre cette fonctionnalité exacte et est sans aucun doute que je recommande mettre en œuvre une telle communication avec le serveur.
Autres conseils
Si le serveur pourrait faire une connexion sortante à un bus de service vous pourriez implament un type de rappel. De cette façon, le client / serveur aurait pas besoin de connaître l'autre du tout, juste le bus de service de confiance. Voir service .NET Bus
Vous voulez regarder dans WSDualHttpBinding
Le WSDualHttpBinding fournit la même en charge les protocoles de services Web comme WSHttpBinding, mais pour une utilisation avec contrats duplex. WSDualHttpBinding prend en charge uniquement la sécurité SOAP et exige une messagerie fiable. Cette la liaison exige que le client dispose d'un URI public qui fournit un rappel point final pour le service. C'est fourni par le ClientBaseAddress. UNE double liaison expose l'adresse IP le client au service. Le client devrait utiliser la sécurité pour assurer que ne se connecte aux services qu'il a confiance.
Sans WCF, vous pouvez essayer d'utiliser XMPP pour obtenir cette fonctionnalité en cours. Il y a un article sur InfoQ à ce sujet et d'autres systèmes. Bien que l'article stipule que XMPP ne peut pas être utilisé sur HTTP, vous pouvez lorsque vous utilisez BOSH .
Il existe des bibliothèques .NET disponibles agsXMPP pour nommer un.
L'entreprise où je travaille commence à l'utiliser pour les notifications push de mise à jour à une demande pour rafraîchir les parties de l'interface utilisateur.
Google pour « WCF duplex ». Je l'ai utilisé avec succès ce en utilisant netTcpBinding (à travers les continents), mais je ne suis pas sûr sur basicHttpBinding.
Cependant, il nécessite le serveur de rappeler au client. Si le serveur ne peut pas le faire, le scrutin peut être votre seule option ...
Si le serveur ne peut pas appeler le client (et il ne devrait pas en général), vous devriez avoir le client le vote serveur que vous avez spécifié. puisque vous avez fondation WCF déjà en place, il suffit d'ajouter une opération pour cela.