Wie informiert ein WCF-Server einen WCF-Client über Änderungen?(Bessere Lösung als einfaches Abfragen, z. B.Komet oder lange Umfrage)
-
19-09-2019 - |
Frage
siehe auch "WCF drückt über Firewall auf den Kunden"
Ich benötige einen WCF-Client, der eine Verbindung zu einem WCF-Server herstellt und dann einige der Daten verarbeitet Änderungen Auf dem Server müssen die Clients aktualisieren seine Anzeige.
Da zwischen den Clients und dem Server wahrscheinlich eine Firewall vorhanden ist.
- Die gesamte Kommunikation muss über HTTP erfolgen
- Der Server kann keinen (physischen) ausgehenden Anruf an den Client tätigen.
Da ich sowohl den Client als auch den Server schreibe, muss ich die Lösung nicht nur auf die Verwendung von Soap usw. beschränken.
Ich suche einen Einbau-Surport für „lange Umfrage" / "Komet" usw
Vielen Dank für die informativste Antwort von Drew Marsh zur Implementierung langer Abfragen in WCF.Ich dachte jedoch, dass das wichtigste „Verkaufsargument“ von WCF darin besteht, dass man so etwas tun kann, indem man einfach die zu verwendenden Kanäle in der Konfigurationsdatei konfiguriert. Ich möchte beispielsweise einen Kanal, der logischerweise in beide Richtungen geht, aber nur physisch eingeht.
Lösung
Für mich hört es sich so an, als wüssten Sie die Antwort bereits:Verwenden Sie lange Abfragen.:) Ich schätze, das Einzige, was noch zu erklären bleibt, ist, wie Sie dies mit WCF und auf die effizienteste Art und Weise erreichen können.
Die Grundlagen:
- Entscheiden Sie zunächst, wie lange jede „lange Umfrage“ dauern soll.Aus Gründen der Argumentation werde ich 5-Minuten-Timeouts wählen.
- Ändern Sie auf der clientseitigen Bindung die
sendTimeout="00:05:00"
. - Genau wie bei der Verwendung von XmlHttpRequest (XHR) für lange Abfragen müssen Sie, wenn das Timeout tatsächlich auftritt, es erkennen und die nächste Abfrageanforderung erneut ausgeben.Dies ist in WCF recht einfach, da es eine spezielle Ausnahme gibt:
TimeoutException
, die Sie erkennen können, um leicht zu erkennen, dass dies das Problem war vs.eine andere Ausnahme. - Abhängig davon, wie Sie Ihren WCF-Dienst hosten, müssen Sie sicherstellen, dass er sich selbst so konfiguriert, dass die Verarbeitung bis zu 5 Minuten dauert.Aus reiner WCF-Perspektive sollten Sie sicherstellen, dass Sie Folgendes festlegen
receiveTimeout="00:05:00"
.Wenn Sie jedoch innerhalb von ASP.NET hosten, müssen Sie auch die ASP.NET-Laufzeitumgebung so konfigurieren, dass sie ein höheres Zeitlimit hat, was mithilfe von erfolgt<httpRuntime executionTimeout="300" />
(Notiz: die Maße für dieses Attribut werden in Sekunden angegeben).
Effizient beim Kunden sein
Wenn Sie Ihren Client nur so einrichten, dass er den Dienst synchron aufruft und der Client 5 Minuten lang blockiert, während er auf eine Antwort wartet, ist das keine sehr effiziente Nutzung der Systemressourcen.Sie könnten diese Aufrufe an Hintergrundthreads senden, aber das wird immer noch eine Thread-Ressource belasten, während der Aufruf aussteht.Der effizienteste Weg, damit umzugehen, ist die Verwendung asynchroner Vorgänge.
Wenn Sie Ihre Serviceverträge manuell erstellen, empfehle ich Ihnen, einen Blick darauf zu werfen diesen Abschnitt auf MSDN weiter OperationContractAttribute.AsyncPattern
Einzelheiten zum Hinzufügen eines BeginXXX
/EndXXX
asynchrones Methodenpaar für jeden Ihrer Aufrufe.Wenn Sie jedoch verwenden svcutil
Um Ihre Betriebsverträge für Sie zu generieren, müssen Sie lediglich die übergeben, damit asynchrone Methoden generiert werden /async
Option in der Befehlszeile.Weitere Einzelheiten zu diesem Thema finden Sie unter Schauen Sie sich das Thema „Synchronous and Asynchronous“ auf MSDN an.
Nachdem Sie nun Ihre asynchronen Vorgänge definiert haben, ähnelt das Muster stark der Arbeit mit XHR.Du rufst an BeginXXX
Methode, an die Sie übergeben ein AsyncCallback
delegieren.Der BeginXXX
Die Methode gibt Ihnen eine zurück IAsyncResult
, an dem Sie entweder festhalten können, wenn Sie auf den Vorgang warten möchten (in fortgeschritteneren Szenarien), oder ihn ignorieren können. Anschließend sendet die WCF-Infrastruktur die Anforderung asynchron an den Server und wartet hinter den Kulissen auf eine Antwort.Wenn eine Antwort eingeht oder eine Ausnahme auftritt, der Rückruf, den Sie an übergeben haben BeginXXX
Methode wird aufgerufen.Innerhalb dieser Rückrufmethode müssen Sie die entsprechende aufrufen EndXXX
Methode, die die übergibt IAsyncResult
das wird dir übergeben.Während des Anrufs beim EndXXX
-Methode müssen Sie eine Ausnahmebehandlung einsetzen, um jede Art von logischem Fehler zu behandeln, der möglicherweise beim Aufrufen der Methode aufgetreten ist. Dies ist jedoch auch der Punkt, an dem Sie den Fehler jetzt abfangen können TimeoutException
wir haben vorhin darüber gesprochen.Vorausgesetzt, Sie haben eine gute Antwort erhalten, werden die Daten vom zurückgegeben EndXXX
Rufen Sie an und Sie können auf diese Daten auf jede sinnvolle Weise reagieren.
NOTIZ: Eine Sache, die Sie bei diesem Muster beachten sollten, ist die Art des Einfädelns.Die asynchronen Rückrufe von WCF werden in einem Thread von empfangen Der verwaltete Thread-Pool.Wenn Sie planen, die Benutzeroberfläche in einer Technologie wie WPF oder WinForms zu aktualisieren, müssen Sie sicherstellen, dass Sie die Aufrufe mithilfe von an den UI-Thread zurückmarshallen Invoke
oder BeginInvoke
Methoden.
Effizient auf dem Server sein
Wenn wir uns Sorgen um die Effizienz des Clients machen, sollten wir uns das doppelte Sorgen machen, wenn es um den Server geht.Offensichtlich stellt diese Art von Ansatz höhere Anforderungen an die Serverseite, da eine Verbindung offen und ausstehend bleiben muss, bis es einen Grund gibt, eine Benachrichtigung an den Client zurückzusenden.Die Herausforderung hierbei besteht darin, dass Sie die WCF-Laufzeit nur mit der Verarbeitung derjenigen Clients verknüpfen möchten, denen tatsächlich ein Ereignis gesendet wird.Alles andere sollte einfach schlafen und darauf warten, dass das Ereignis eintritt.Glücklicherweise funktioniert das gleiche asynchrone Muster, das wir gerade auf der Clientseite verwendet haben, auch auf der Serverseite.Allerdings gibt es mittlerweile einen großen Unterschied:Jetzt Du muss die zurückgeben IAsyncResult
(und damit ein WaitHandle
) von dem BeginXXX
Methode, die die WCF-Laufzeit dann auf das Signal wartet, bevor sie Ihre aufruft EndXXX
Methode.
Du wirst nicht Abgesehen von den Links, die ich bereits zuvor bereitgestellt habe, finden sich in MSDN viele weitere Dokumentationen, und leider sind die Beispiele zum Schreiben eines Async-Dienstes nicht sehr nützlich.Das gesagt, Wenlong Dong hat einen Artikel über die Skalierung von WCF-Diensten mit dem asynchronen Modell geschrieben vor einiger Zeit, das ich Ihnen wärmstens empfehlen kann.
Darüber hinaus kann ich ehrlich gesagt nicht viele Ratschläge dazu geben, wie Sie das asynchrone Modell auf der Serverseite am besten für Sie implementieren können, da es völlig davon abhängt, aus welcher Art von Datenquelle Ihre Ereignisse überhaupt stammen.Datei-E/A?Eine Nachrichtenwarteschlange?Eine Datenbank?Gibt es eine andere proprietäre Software mit eigenem Messaging-Dienst, die Sie mit einer Fassade versehen möchten?Ich weiß es nicht, aber sie sollten alle eigene asynchrone Modelle anbieten, auf die Sie Ihren eigenen Dienst zurückgreifen können, um ihn so effizient wie möglich zu gestalten.
Aktualisiertes Rezept
Da dies eine beliebte Antwort zu sein scheint, dachte ich, ich sollte angesichts der jüngsten Veränderungen in der Landschaft hierher zurückkommen und ein Update bereitstellen.An dieser Stelle gibt es nun eine .NET-Bibliothek namens SignalR das genau diese Funktionalität bietet und ich würde auf jeden Fall empfehlen, eine solche Kommunikation mit dem Server zu implementieren.
Andere Tipps
Wenn der Server eine ausgehende Verbindung zu einem Service-Bus machen konnte könnten Sie eine Art von Anruf implament zurück. Auf diese Weise der Client / Server nicht brauchen überhaupt umeinander zu wissen, nur die Berufung Service Bus. Siehe .NET Service Bus
Sie suchen möchten in WSDualHttpBinding
Das WSDualHttpBinding stellt den gleiche Unterstützung für Web-Service-Protokolle als WSHttpBinding, aber für den Einsatz mit Duplex-Verträge. WSDualHttpBinding nur unterstützt SOAP Sicherheit und erfordert zuverlässiges Messaging. Diese Bindung erfordert, dass der Client eine öffentliche URI, die einen Rückruf bietet Endpunkt für den Dienst. Das ist durch die ClientBaseAddress vorgesehen. EIN Dual-Bindung macht die IP-Adresse der Client an den Dienst. Der Kunde Sicherheit verwenden soll, dass es, um sicherzustellen, nur eine Verbindung zu Diensten er vertraut.
Während Sie nicht WCF könnten versuchen, XMPP zu verwenden, die Funktionalität zu erhalten gehen. Es gibt einen Artikel über InfoQ über sie und andere Systeme. Während der Artikel heißt es, dass XMPP nicht über HTTP verwendet werden kann, können Sie bei der Verwendung von BOSH .
Es gibt .NET-Bibliotheken verfügbar agsXMPP einen nennen.
Das Unternehmen, in dem ich arbeiten beginnt, es zu benutzen Update-Benachrichtigungen an eine Anwendung zu drängen es Teile der Benutzeroberfläche zu aktualisieren.
Google für „ WCF-Duplex “. Ich habe diese erfolgreich mit netTcpBinding (über Kontinente) verwendet, aber ich bin mir nicht sicher über Basichttpbinding.
Allerdings hat es den Server erfordern zurück an den Client zu nennen. Wenn der Server nicht erlaubt, dies zu tun, Polling Ihre einzige Option sein kann ...
Wenn der Server den Client nicht nennen (und es sollte nicht in der Regel) sollten Sie die Client-Abfrage haben den Server als Sie angegeben haben. da Sie WCF Fundament haben bereits vorhanden, fügen Sie einfach eine Operation für das.