Architekturbewertung von .NET Remoting

 

Pat Martin
Microsoft Corporation

Mai 2003

Gilt für:
    Microsoft® .NET Framework
    Microsoft® .NET Remoting

Zusammenfassung: Dieser Artikel richtet sich an alle, die die Verwendung von .NET Remoting als Teil eines verteilten mehrschichtigen Anwendungsentwurfs in Betracht ziehen. Es beschreibt die Fähigkeiten der Technologie aus der Perspektive eines Entwicklers, der sowohl von dem praktischen RPC-Mechanismus profitiert hat, den sie bietet, als auch ein wenig unter ihren Mängeln gelitten hat. Es wird angenommen, dass der Leser mit .NET Remoting vertraut ist, zumindest konzeptionell, wenn nicht praktisch.

Der Abschnitt Produktfeatures ist nützlich für jemanden, der etwas (möglicherweise) mit Remoting entwerfen möchte. Der Abschnitt Bewährte Methoden ist nützlich für alle, die etwas mit Remoting erstellen möchten. Der Abschnitt Remoting und Webdienste ist ein Versuch, einige der Verwirrungen zu beseitigen, die in bezug auf die Verwendung welcher Technologie bestehen. Die Zusammenfassung ist ein Versuch, den Inhalt auf eine einzelne Seite zu verdichten.

Inhalte

Übersicht
Produktfeatures
Bewährte Methoden für die Verwendung von Remoting
Remoting und ASP.NET-Webdienste
Kurzfassung
Zusätzliche Ressourcen

Übersicht

.NET Remoting wurde als die ausgewählte Technologie zum Verwalten von RPC zwischen Anwendungsdomänen beschrieben. Anwendungsdomänen sind die Isolationseinheit für die Common Language Runtime. Sie werden in einem Prozess erstellt und dort ausgeführt. Dies steht im Gegensatz zur Inter Process Communication zwischen CLR und non-CLR Managed Processes (Interop). Letztere Art der RPC-Kommunikation, insbesondere über das "Web", wird als Domäne von Webdiensten (zur Verwendung des generischen Begriffs) angesehen. Leider wurde diese scheinbar klare Unterscheidung durch die Möglichkeit getrübt, .Net Remoting-Server unter IIS zu hosten, wie im Artikel Einführung in Microsoft .NET Remoting Framework erläutert:

".NET Remoting-Objekte können als Webdienst verfügbar gemacht werden, indem sie in IIS gehostet werden..."

Es kann ein gewisses Maß an Verwirrung seitens einiger Microsoft-Kunden in Bezug auf .NET Remoting geben. Einige häufige Fragen, die mir gestellt wurden, sind "Wann sollten wir Remoting verwenden?" "Wann unterstützt Remoting NTLM?" "Wie kann ich Remoteunterhaltungen schützen?" "Was ist mit COM+?" und "Wie verwaltet Remoting Transaktionen?"

Zusätzlich zu einigen dieser Fragen werden in diesem Artikel einige bewährte Methoden für die Verwendung von .NET Remoting beschrieben und eine Übersicht über die derzeit bereitgestellten Funktionen bereitgestellt. Die Executive Summary zeigt mögliche zukünftige Richtungen für die Technologie an, insbesondere in Bezug auf Webdienste und die sich abzeichnenden Spezifikationen der Global XML Web Services Architecture (GXA).

Der Abschnitt Produktfeatures basiert weitgehend auf Informationen, die auf der TechED N.Z. 2002 vorgestellt wurden. In dieser Präsentation wurden die verschiedenen Möglichkeiten hervorgehoben, wie Remoting in einer verteilten Lösung verwendet werden kann, und half, die Vorteile von Remoting zu verdeutlichen, zusammen mit dem Hinweis auf seine Defizite.

Der Abschnitt Best Practices basiert auf persönlichen Erfahrungen bei der Verwendung von Remoting in einer mehrstufigen .NET-Anwendung. Während der Entwicklung wurden eine Reihe einfacher bewährter Methoden entwickelt, die hier aufgeführt sind.

Einige Abschnitte enthalten Material, das auf informellen Gesprächen mit Personen innerhalb von Microsoft basiert, die über ein fundiertes Verständnis der Technologie und ihrer Richtung verfügen. Die dargestellten Informationen sind in keiner Weise repräsentativ für zukünftige Produktlieferungspläne oder -zeitpläne.

Produktfeatures

In diesem Abschnitt werden die Funktionen und Produktfeatures beschrieben, die von .NET Remoting angeboten werden.

Client/Server-Kommunikation

.NET Remoting bietet eine nützliche Möglichkeit, synchrone und asynchrone RPC-Unterhaltungen domänenübergreifend zu verwalten. Der Remoteobjektcode wird entweder auf dem Server ausgeführt, wie es bei serveraktivierten und clientaktivierten Objekten der Fall ist. oder auf dem Client, bei dem das Remoteobjekt über die Client/Server-Verbindung serialisiert wurde. In beiden Fällen ist die programmgesteuerte Sprache nach Abschluss der Initialisierung und Konfiguration sehr einfach, für die die Codierungsanforderungen minimal sind. Die Verwendung eines Remoteobjekts (per Proxy im Fall von Marshal by Reference) ist für den Programmierer transparent. Frühere Windows-RPC-Mechanismen erforderten beispielsweise intimes Typ- und Marshallingwissen mithilfe von IDL-Tools und haben die Verwaltung von RPC-Client- und Server-Stubs für den Entwickler verfügbar gemacht. Remoting macht einen viel saubereren Job bei der Bereitstellung von RPC für .NET, und die Verwendung von leicht verständlichen .NET-Datentypen beseitigt die sehr reale Bedrohung von Typkonflikten, die mit früheren RPC-Mechanismen bestanden.

Standardmäßig kann Remoting für die Kommunikation mit HTTP- oder TCP-Protokollen konfiguriert werden, wobei die Nachrichtenformate entweder XML-codiert SOAP oder native Binärdatei sind. Benutzerdefinierte Protokolle (Kanäle) oder Nachrichtenformate (Formatierer) können vom Entwickler erstellt und bei Bedarf vom Remoting-Framework verwendet werden. Ports können sowohl von Server- als auch von Clientkomponenten ausgewählt werden, ebenso wie die Auswahl der Kommunikationsprotokolle. Ein großer Gewinn hier ist, dass diese grundlegende Kommunikation sehr einfach zu erreichen ist.

Es gibt jedoch Optionen für die Art der Kommunikation, die in Bezug auf die Zustandsverwaltung ausgewählt wurde. Der Rest dieses Abschnitts beschreibt die verschiedenen Optionen für die Kommunikation, die Remoting bietet, zusammen mit den zugehörigen Entwurfsauswirkungen.

Vom Server aktivierte Objekte

Vom Server aktivierte Objekte sind Objekte, deren Lebensdauer vom Server gesteuert wird. Sie werden vom Server nur nach Bedarf erstellt, wenn der Client die erste Methode für das Objekt aufruft. Serveraktivierte Objekte unterstützen nur Standardkonstruktoren. Um ein Remoteobjekt mit parametrisierten Konstruktoren zu verwenden, können Sie die Clientaktivierung oder die dynamische Veröffentlichung verwenden (siehe unten). Serveraktivierte Objekte werden auch als bekannte Objekttypen bezeichnet, da ihr Speicherort (URL) vorab veröffentlicht und bekannt ist. Es gibt zwei Aktivierungsmodi für vom Server aktivierte Objekte, Singleton und SingleCall, die im Folgenden beschrieben werden. Um eine instance eines serveraktivierten Typs zu erstellen, können Sie Ihre Anwendung entweder programmgesteuert oder über eine statische Konfiguration konfigurieren. Die Konfiguration der Serveraktivierung ist ziemlich einfach. Beispiel: Der folgende Codeausschnitt

<service>
  <wellknown mode="SingleCall" type="Hello.HelloService, Hello" 
                   objectUri="HelloService.soap" />
</service>

stellt einen vom Server aktivierten (wohlbekannten) Typ dar, bei dem der Aktivierungsmodus auf SingleCall festgelegt ist. Ausführliche Informationen zum Konfigurieren von serveraktivierter Remoting finden Sie im .NET Framework-Entwicklerhandbuch "Serverseitige Registrierung" auf MSDN.

Singleton

Diese Objekte folgen dem klassischen Singleton-Entwurfsmuster, da nie mehr als ein instance zu einem beliebigen Zeitpunkt im Arbeitsspeicher vorhanden ist und alle Clients von diesem instance bedient werden. Beachten Sie jedoch, dass diesen Typen eine Standardlebensdauer zugeordnet ist (siehe Abschnitt Objektlebensdauerverwaltung weiter unten). Dies bedeutet, dass Clients nicht unbedingt immer einen Verweis auf dieselbe instance der remotable-Klasse erhalten. Letztere Tatsache hat interessante Auswirkungen auf die Zustandsverwaltung und ist der Ort, an dem dieses Remotingmuster vom klassischen Singleton-Modell abweicht (was erfordert, dass die Objektidentität identisch sein muss). Es gibt zwei Möglichkeiten, dieses Problem zu lösen, wenn das klassische Singleton-Zustandsverwaltungsmuster für Ihren Entwurf erforderlich ist. Eine Option besteht darin, das Standardverhalten des Objektleasings so zu überschreiben, dass das Objekt im Arbeitsspeicher bleibt, solange die Hostanwendungsdomäne ausgeführt wird. Der folgende Codeausschnitt veranschaulicht, wie dies erreicht werden kann:

public class MyClass : MarshalByRefObject
{
  public override Object InitializeLifetimeService()
  {
      return null;
  }
}

Wie bereits erwähnt, sperrt dieser Mechanismus das Objekt im Arbeitsspeicher und verhindert, dass das Objekt wiederverwendet wird, jedoch nur so lange, wie die Hostanwendung ausgeführt wird. Sollte iis oder der IIS-Prozess, der die Remotingsitzung hostet, wiederverwendet werden (was aus verschiedenen Gründen auftreten kann), wird das Objekt zerstört.

Um mit Remoting vollständig von threadsicheren Singleton-Zustandsdaten abhängig zu sein, müssen wir drei Dinge tun:

  1. Überschreiben Sie den Leasingmechanismus so, dass die Lease unendlich ist, wie oben gezeigt.
  2. Hosten Sie den Remoteserver in einem Prozess, der von uns selbst erstellt wird, z. B. einen Systemdienst, über den wir die volle Lebensdauer steuern. Obwohl dieser Prozess auch wiederverwendet werden kann, wäre dies eine explizitere Aktion und würde weniger wahrscheinlich unbemerkt bleiben als ein IIS-Workerprozess, der recycelt wird. Weitere Informationen zu diesem Mechanismus finden Sie im Abschnitt Produktfeatures unten.
  3. Entwickeln Sie den Remoteserver so, dass er threadsicher ist, da mehrere Threads verwendet werden, um gleichzeitig Anforderungen von Clients zu erfüllen. Dies bedeutet beispielsweise, gleichzeitige Schreibvorgänge in freigegebene Ressourcen zu verwalten und sich im Allgemeinen um den freigegebenen Zugriff auf statischen Arbeitsspeicher zu kümmern.

Singlecall

SingleCall-Remoteservertypen verfügen immer über eine instance pro Clientanforderung. Der nächste Methodenaufruf wird von einem anderen instance verwaltet. In Bezug auf das Design ist die Funktionalität, die von SingleCall-Typen bereitgestellt wird, sehr einfach. Mit diesem Mechanismus wird keine Zustandsverwaltung bereitgestellt, was schlecht ist, wenn Sie einige möchten, aber ideal, wenn Sie dies nicht möchten. Vielleicht ist Ihnen nur der Lastenausgleich und die Skalierbarkeit wichtig als der Zustand. In diesem Fall ist dieser Modus eine ideale Wahl, da Sie genau eine instance pro Anforderung erhalten. Der Entwickler kann, wenn er möchte, eine eigene Zustandsverwaltung für SingleCall-Objekte bereitstellen, aber diese Zustandsdaten würden sich nicht in den Objekten selbst befinden, da mit jedem neuen Methodenaufruf eine neue Objektidentität instanziiert wird.

Dynamische Veröffentlichung

Der letzte Typ der zu berücksichtigenden Serveraktivierungsmethode ist die dynamische Veröffentlichung. Dies ist eine Art der Serveraktivierung, die mehr Kontrolle über die Objekterstellung bietet, indem sie einen programmgesteuerten Veröffentlichungsmechanismus bereitstellt. Dadurch kann ein bestimmtes Objekt unter einer bestimmten URL veröffentlicht werden, optional mit einem parametrisierten Konstruktor. Architektonisch sollte dies als subtile Variante eines vom Server aktivierten Singleton-Typs betrachtet werden. Informationen zur dynamischen Veröffentlichung finden Sie im .NET Framework Entwicklerhandbuch.

Vom Client aktivierte Objekte

Vom Client aktivierte Objekte werden auf dem Server erstellt, wenn der Client new oder Activator.CreateInstance() aufruft. Der Client selbst kann mithilfe des Lebenslangen Leasingsystems an der Lebensdauer dieser Instanzen teilnehmen. Dieser Aktivierungsmechanismus bietet den größten Spielraum in Bezug auf die Entwurfsflexibilität. Bei der Clientaktivierung wird eine Aktivierungsanforderung an den Server gesendet, wenn ein Client versucht, das Objekt zu aktivieren. Dieser Mechanismus ermöglicht sowohl parametrisierte Konstruktoren als auch eine eindeutige Client-Verbindungsstatusverwaltung. Bei der Clientaktivierung wird jeder Client von einem eigenen spezifischen Server instance bedient, was das Speichern des Objektzustands über mehrere Aufrufe erleichtert. Man muss bei der Verwendung dieser Objekte umsichtig sein, aber es ist leicht zu vergessen, dass die Konversation verteilt ist und dass das Objekt nicht nur außerhalb des Prozesses, sondern im Fall einer mehrschichtigen App wahrscheinlich auch außerhalb des Computers ist – das Festlegen einer Eigenschaft über das Internet wäre nicht zu umsichtig. Chunky anstelle von chatzigen Schnittstellen sollte hier die Regel sein: Möglicherweise müssen wir eine hohe Kohäsion / lose Kopplung für die Leistung abwägen. Um eine instance eines clientaktiven Typs zu erstellen, können Sie Ihre Anwendung entweder programmgesteuert konfigurieren oder eine statische Konfiguration verwenden. Die Konfiguration der Clientaktivierung auf dem Server ist ziemlich einfach. Beispiel: der folgende Codeausschnitt

<service>
  <activated type="Hello.HelloService, Hello" 
             objectUri="HelloService.soap" />
</service>

stellt einen ClientActivated-Typ dar. Beachten Sie, dass wir keine URL mehr benötigen, da für clientaktivierte Typen der Typ allein für die Aktivierung ausreicht. Außerdem wurde das bekannte Tag durch das aktivierte Tag ersetzt. Ausführliche Informationen zum Konfigurieren von clientaktivem Remoting finden Sie im .NET Framework-Entwicklerhandbuch "Registrieren von Remoteobjekten mithilfe von Konfigurationsdateien" auf MSDN.

Erweiterungen

Während der Verarbeitung eines Remotemethodenaufrufs sendet .NET Remoting formatierte "Nachrichten" vom Client an den Server entlang von Remoting "Kanälen". Sowohl die Nachrichtenformate als auch die Kanäle selbst sind vollständig erweiterbar und anpassbar. Entweder der Standardkanal oder der Formatierer kann durch benutzerdefinierte Komponenten ersetzt werden. Während der Übertragung der Nachricht kann sie an verschiedenen "Senkenpunkten" abgefangen und geändert werden, was eine benutzerdefinierte Verarbeitung der Nachricht ermöglicht (z. B. Nachrichtenverschlüsselung). Der Anpassungsmechanismus wird im .NET Framework Entwicklerhandbuch (Senken und Senkenketten) beschrieben, und eine Reihe von benutzerdefinierten Kanälen und Formatierern wird bereits im Internet angezeigt (z. B. gibt es eine Named Pipe-Kanalimplementierung). Diese Erweiterbarkeit wird in den meisten Fällen nicht interessant sein, da die mit der Technologie bereitgestellten Standardformatierer und -kanäle bereits auf die größte Reichweite ausgerichtet sind (d. a. TCP und HTTP speziell zusammen mit SOAP-Nachrichtenformatierern). Es sollte daran erinnert werden, dass diese Funktion jedoch während der anfänglichen Entwurfsphase vorhanden ist, in der verschiedene Lösungsoptionen in Betracht gezogen werden.

Ausnahmeverteilung

.NET Remoting unterstützt die Ausnahmeweitergabe über Remotinggrenzen hinweg vollständig. Dies ist eine wesentliche Verbesserung gegenüber der Verwendung von Fehlercodes, z. B. wie bei DCOM.

Bei Remoting-Ausnahmen empfiehlt es sich, Ihre Ausnahmeklasse als serialisierbar zu markieren und die ISerializable-Schnittstelle zu implementieren. Dadurch kann die Ausnahme ordnungsgemäß über die Remotinggrenze serialisiert werden, und es wird auch ermöglicht, dass der Ausnahme während des Aufbaus benutzerdefinierte Daten hinzugefügt werden. Eine bewährte Methode besteht darin, Eine eigene Ausnahmeklasse für Ausnahmen zu definieren, die entfernt werden müssen und bei deren Verwendung konsistent sein muss. Stellen Sie sicher, dass alle Ausnahmen auf diese Weise abgefangen und ordnungsgemäß weitergegeben werden, und lassen Sie keine nicht behandelten Ausnahmen über die Remotinggrenze hinweg zu.

Verwaltung der Objektlebensdauer

.NET Remoting bietet einen umfassenden Mechanismus zum Verwalten der Lebensdauer von Remoteobjekten. Wenn unser Serverobjekt keinen Zustand aufweist (z. B. wie bei einem SingleCall-Objekt ), müssen wir uns in keiner Weise mit diesem Prozess befassen. Wir lassen die Remoting-Infrastruktur einfach zu, was sie tut, und unsere Objekte werden bei Bedarf garbage collection. Wenn der Zustand entweder serveraktiviert oder vom Client aktivierte Objekte gespeichert wird, müssen wir möglicherweise am Lebenszyklusverwaltungsprozess teilnehmen: Objektleasing. Wir haben bereits eine einfache (und nützliche) Möglichkeit der minimalen Beteiligung gesehen, die darin besteht, die InitializeLifetimeService-Methode zu überschreiben, wie in der Obigen Beschreibung von Singletons gezeigt. Auf diese Weise können wir unsere Objekte so lange beibehalten, wie die Prozesse, die sie hosten, ausgeführt werden. Wie funktioniert dieser Objektlebensdauerprozess?

Der Mechanismus von Remoting für die Objektverwaltung basiert auf dem Prinzip des Leasings: Sie besitzen nie ein Objekt, Sie leihen es sich einfach aus, und solange Sie die Zahlungen aufrecht erhalten, können Sie es weiterhin verwenden. Dieser Prozess wird weiter unten beschrieben. Zunächst jedoch ein paar Worte zur Vorgehensweise der COM-Welt mit der Objektbereinigung. DCOM verwendet eine Kombination aus Ping- und Verweiszählungsmethoden, um zu bestimmen, ob Objekte noch ausgeführt werden. Dies ist sowohl fehleranfällig als auch netzwerkintensiv. Das gesamte Prinzip der Referenzzählung war im schlimmsten Fall nie vollständig verstanden und bestenfalls fragil. Es gab (und gibt es) eine Reihe einfacher Regeln, die angewendet werden mussten, damit die Referenzzählung funktioniert. Die IUnknown-Schnittstelle für ein COM-Objekt enthält addRef - und Release-Methoden , die vom Entwickler zu den entsprechenden Zeiten aufgerufen werden müssen. Manchmal haben Programmierer dies falsch gemacht, was dazu führte, dass Objekte nicht entfernt wurden, und zu zugehörigen Speicherverlusten.

Im Gegensatz dazu verwendet das leased-basierte Lebensdauerverwaltungssystem von Remoting eine Kombination aus Leases, Sponsoren und einem Lease-Manager. Jede Anwendungsdomäne enthält einen Lease-Manager, der Verweise auf ein Leaseobjekt für jedes Singleton- oder clientaktivierte Objekt in seiner Domäne enthält. Jeder Lease kann 0 oder mehr zugeordnete Sponsoren haben, die in der Lage sind, den Mietvertrag zu verlängern, wenn der Lease-Manager feststellt, dass die Lease abgelaufen ist. Diese Leasefunktion wird von der Remoting-Infrastruktur über die ILease-Schnittstelle bereitgestellt und durch den Aufruf von InitializeLifetimeService abgerufen, den wir oben bereits gesehen haben. Die ILease-Schnittstelle definiert eine Reihe von Eigenschaften, die zum Verwalten der Lebensdauer von Objekten verwendet werden:

  • InitialLeaseTime. Bestimmt, wie lange die Lease anfänglich gültig ist.
  • RenewOnCallTime. Nach jedem Methodenaufruf wird die Lease für diese Zeiteinheit erneuert.
  • SponsorshipTimeout. Wie lange Remoting nach Ablauf der Leasebenachrichtigung des Sponsors wartet?
  • CurrentLeaseTime. Gibt an, wie lange die Lease abläuft (schreibgeschützter Wert).

Wenn ein Leasing abläuft, benachrichtigt der Lease manager alle Leasingsponsoren, um zu fragen, ob sie den Mietvertrag verlängern möchten. Wenn keine der zugehörigen Objektverweise vorhanden sind, werden die zugehörigen Objektverweise freigegeben.

Sponsoren sind Objekte, die Leases für Remoteobjekte verlängern können. Um Sponsor zu werden, muss Ihre Klasse von MarshalByRefObject abgeleitet und die ISponsor-Schnittstelle implementieren. Ein Mietvertrag kann viele Sponsoren haben. Ein Sponsor kann an vielen Mietverträgen teilnehmen.

Die Mechanismen dieser Leaseverwaltung in Bezug auf die Programmierung für diese Schnittstellen werden in der .NET Framework Developer es Guide-Dokumentation zu Lebensdauerleases beschrieben und daher hier nicht wiedergegeben. BeachtenSwert ist jedoch, dass dieser umfangreiche Mechanismus für die Verwaltung der Lebensdauer zustandsbehafteter Remoteobjekte vorhanden ist. Wie bereits erwähnt, können Sie es entweder vollständig ignorieren, es verwenden, um ein Objekt im Arbeitsspeicher zu speichern, während der Prozesscontainer ausgeführt wird, oder sie können vollständig in den Leasingmechanismus einbezogen werden.

Remoteserverhosting

Es gibt eine Reihe von Optionen für das Hosten eines .NET Remoted-Servers, die in zwei allgemeine Kategorien passen, die als Nächstes beschrieben werden.

IIS-Hosting unter ASP.NET

Als Standardfunktionalität ist die Möglichkeit verfügbar, ein serverseitiges Remoteobjekt unter IIS zu hosten. Dies bringt viele Vorteile mit sich, einschließlich Unterstützung für Sicherheit und Skalierbarkeit.

So hosten Sie Ihr Objekt unter IIS:

  1. Entwickeln Sie Ihre Remoteklasse, und erben Sie von MarshalByRefObject (oder deklarieren Sie die Klasse als serialisierbar).
  2. Erstellen Sie mithilfe des IIS-Verwaltungs-Managers eine virtuelle Webanwendung.
  3. Platzieren Sie die Assembly, die Ihre Klasse enthält, im Unterordner bin Ihrer virtuellen Webanwendung.
  4. Erstellen Sie eine web.config-Datei, die Ihre Remoting-Serverkonfigurationsdefinition enthält, und platzieren Sie sie im virtuellen Stammverzeichnis Ihrer Webanwendung.

Das ist alles. Es gibt jedoch einige Einschränkungen, die Sie beachten sollten:

  • Sie können keinen Anwendungsnamen für das IIS-Hosting angeben, da es sich um den Namen der virtuellen App handelt.
  • Sie müssen httpchannel verwenden.
  • Wenn Ihr Remoting-Client auch eine Web-App ist, müssen Sie remotingConfiguration.Configure während des Startvorgangs aufrufen. Dies befindet sich in der Regel in der Application_Start-Methode Ihrer Global.asax-Datei. Sie können das <Clienttag> nicht verwenden, um Ihre Clientwebanwendung automatisch zu konfigurieren.
  • Geben Sie keinen Port an, da IIS die Portzuordnung übernimmt. Sie können weiterhin den IIS-Administrator verwenden, um bei Bedarf einen Port für die virtuelle Anwendung anzugeben.

Die Remotinganwendungsdomäne wird innerhalb des Aspnet_wp.exe-Arbeitsprozesses gehostet und übernimmt standardmäßig die Identität dieses Prozesses.

Hinweis Es gibt derzeit einen Fehler in ASP.NET, der erfordert, dass die Prozessidentität für den Aspnet_wp.exe Arbeitsprozess entweder auf "System" oder ein lokales Computerkonto festgelegt werden muss. die Standardeinstellung "computer" in machine.config nicht ordnungsgemäß konfiguriert ist, was dazu führt, dass ASP.NET Anwendungen mit dem Fehler 500, "interner Serverfehler", fehlschlagen, wenn sie unter IIS auf einem Domänencontroller gehostet werden. Der Fehler liegt wohl in der fehlenden Dokumentation, die beschreibt, wie das Computerkonto entsprechend konfiguriert wird.

Das Hosten unter IIS bietet eine Reihe von funktionalen Vorteilen. Skalierungs-, Threading-, Überwachungs-, Authentifizierungs-, Autorisierungs- und sichere Kommunikationsfeatures sind standardmäßig verfügbar. Der ASP.NET Arbeitsprozesses wird immer ausgeführt und unterliegt einer Optimierung im Hinblick auf die Thread- und Fehlerverwaltung mithilfe des <processModel-Elements> in machine.config. Kurz gesagt, die Vorteile und Funktionen, die IIS zur Verfügung stehen, stehen dem Remoteserver offen.

Es gibt jedoch eine Reihe von Nachteilen: Sie müssen HTTP verwenden, das langsamer ist als TCP. Darüber hinaus kann IIS den ASP.NET Workerprozess durchlaufen, der jeden Singleton-Zustand zerstört. Dies kann je nach Ihren Entwurfsanforderungen ein Problem sein. Der nächste Aufruf eines Clients startet das Singleton erneut. Es ist möglich, IIS so zu konfigurieren, dass ein Arbeitsprozess nicht wiederverwendet wird. Diese Funktion ist jedoch, insbesondere in IIS 5, eingeschränkt und kann weitreichende Folgen haben. Die Quintessenz ist jedoch, dass, wenn die Sicherheit Ihres Remoteservers eine Anforderung ist, IIS-Hosting definitiv der weg ist. Die Leistung ist nur dann ein Problem, wenn sie während des Systemtests/der Nutzung tatsächlich als Problem wahrgenommen wird, und es gibt immer die Möglichkeit, das Problem in der Hardware zu lösen.

Überlegungen zur Authentifizierung unter IIS

Authentifizierungsoptionen

.NET Remoting verfügt nicht über ein eigenes Sicherheitsmodell: Authentifizierung und Autorisierung werden vom Kanal und Hostprozess durchgeführt, in diesem Fall VON IIS. Windows-Authentifizierung wird für Remoting unterstützt und in web.config konfiguriert, indem authentifizierungsmodus="Windows"/>festgelegt <wird. Weder Formulare noch Passport-Authentifizierung werden unterstützt, da Remoting-Clients weder auf Cookies zugreifen noch auf eine Anmeldeseite umgeleitet werden können – Remoteserver sind für die nicht interaktive Verwendung konzipiert.

Übergeben von Anmeldeinformationen an Remoteobjekte

Wenn das Remoteobjekt von IIS gehostet wird (innerhalb des ASP.NET-Arbeitsprozesses) und für Windows-Authentifizierung konfiguriert ist, müssen Sie die zu verwendenden Anmeldeinformationen mithilfe der Credentials-Eigenschaft des Kanals angeben. Wenn dies nicht der Fall ist, führt dies dazu, dass der Remoteaufruf durchgeführt wird, ohne dass Anmeldeinformationen übergeben werden. Diese Auslassung ist eine häufige Ursache für http-Zugriff verweigerte Antworten. Um die Anmeldeinformationen des Prozesses zu verwenden, der den Remoteobjektproxy (den Remoting-Clientprozess) hostet, legen Sie die Eigenschaft credentials des Kanals auf die Vom Prozess-Anmeldeinformationscache verwalteten DefaultCredentials fest. Dies kann entweder deklarativ mithilfe des Kanalelements (für einen Webclient) erfolgen, <d. b. channel ref="http" useDefaultCredentials="true"/> oder programmgesteuert mit dem folgenden Code:

IDictionary channelProperties;
channelProperties = ChannelServices.GetChannelSinkProperties(proxy);
channelProperties["credentials"] = CredentialCache.DefaultCredentials;

Wenn Sie bestimmte Anmeldeinformationen zusammen mit einem Remoteobjektaufruf übergeben möchten, deaktivieren Sie die Verwendung der Standardanmeldeinformationen, d. a. legen Sie <channel ref="http" useDefaultCredentials="false"/> fest, und verwenden Sie den folgenden Code:

IDictionary channelProperties =
ChannelServices.GetChannelSinkProperties(proxy);
NetworkCredential credentials;
credentials = new NetworkCredential("username", "password", "domain");
ObjRef objectReference = RemotingServices.Marshal(proxy);
Uri objectUri = new Uri(objectReference.URI);
CredentialCache credCache = new CredentialCache();
// Substitute "authenticationType" with "Negotiate", "Basic", "Digest",
// "Kerberos" or "NTLM"
credCache.Add(objectUri, "authenticationType", credentials);
channelProperties["credentials"] = credCache;
channelProperties["preauthenticate"] = true;

Hinweis Wenn Sie die Preauthenticate-Eigenschaft auf true festlegen (wie oben), wird ein WWW-Authenticate-Header mit der anfänglichen Anforderung übergeben. Dadurch wird der Webserver beendet, der den Zugriff auf die ursprüngliche Anforderung verweigert und die Authentifizierung für die nachfolgende Anforderung ausführt.

Hosten außerhalb von IIS

Es gibt eine Reihe von Optionen für das Remotehosting außerhalb von IIS. Diese werden als Nächstes aufgeführt.

Hosten in einer Konsolenanwendung

Der Entwickler kann eine Konsolenanwendung schreiben, die die Remoting-Infrastruktur startet und dann einfach "herumhängt". Der einzige Grund, warum es hängen bleiben muss, ist, dass es die Anwendungsdomäne enthält, in der die Remoteaufrufe gehostet werden. Das Schreiben ist äußerst einfach: Rufen Sie einfach die RemotingConfiguration.Configure-Methode auf, und übergeben Sie ihr den Namen Ihrer Remotehost-Konfigurationsdatei, und warten Sie dann, bis ein Ereignis den Prozess beendet, z. B. eine Taste drücken oder eine bestimmte Nachricht empfangen wird.

Dieser Ansatz hat den Vorteil, dass IIS nicht auf der mittleren Ebene erforderlich ist, aber nicht produktionsbereit ist. es ist nützlich für Demos, Entwicklung und Tests. Das soll nicht heißen, dass es überhaupt nichts nützt, nur dass es sehr begrenzt ist.

Hosten in einer GUI-Anwendung

Der Entwickler kann auch eine Windows-GUI-Anwendung schreiben, die die Remoting-Infrastruktur startet und dann einfach "herumhängt". Der einzige Grund, warum die Ausführung fortgesetzt werden muss, ist, dass sie die Anwendungsdomäne enthält, in der die Remoteaufrufe gehostet werden. Der Entwicklungsansatz ist hier wie bei der Konsolenanwendung: Der Remoting-Host kann entweder direkt gestartet oder basierend auf Benutzerinteraktionen gestartet werden. Auch dieser Ansatz hat den Vorteil, dass IIS nicht auf der mittleren Ebene erforderlich ist, und ist für Demos und Tests nützlich. Eine Variante davon wäre eine Peer-to-Peer-Winforms-App (logisch), z. B. eine Chatanwendung. Auch dies wäre von begrenztem Nutzen.

Hosten in einem Systemdienst

Diese Möglichkeit ist interessanter, da die Funktionalität nicht so sehr von der Remoting-Infrastruktur als von der Idee eines Systemdiensts selbst bereitgestellt wird. Systemdienste können so konfiguriert werden, dass sie gestartet werden, wenn der Computer gestartet wird, und so bleiben, bis Sie sie zum Verschwinden auffordern. Dies ist ideal für Remotehosting. Beachten Sie, dass IIS-Anwendungen auch so konfiguriert werden können, dass sie sich ähnlich verhalten, indem sie "Hoher Isolationsmodus" für die virtuelle Anwendung festlegen. Dies hat jedoch eine Reihe von Auswirkungen, die in diesem Artikel nicht behandelt werden. Kunden haben einige schwierige Fragen zu diesem Mechanismus gestellt, der seine Nützlichkeit in Frage stellt. Zunächst einige Vorteile: Wir haben bereits die Vorteile einer Dienstleistung selbst erwähnt. Darüber hinaus haben wir die volle Kontrolle über die Aktivierung des Hostprozesses, z. B. können wir uns für die Verwendung der dynamischen Veröffentlichung oder der Clientaktivierung entscheiden. Wir benötigen IIS nicht, da wir unser Benutzerprofil laden können und wir eine gute Leistung mit binär codierten Nachrichten über TCP erhalten.

Die Nachteile wiegen jedoch ziemlich schwer. Zunächst müssen Sie eigene Authentifizierungs- und Autorisierungsmechanismen erstellen, falls Sie sie benötigen. Der Artikel .NET Remoting Security Solution, Part 1: Microsoft.Samples.Security.SSPI Assembly enthält eine sehr vollständige und detaillierte Beschreibung einer Sicherheitslösung für .NET Remoting, die " ... implementiert einen verwalteten Wrapper um SSPI und stellt die Kernfunktionen bereit, die zum Authentifizieren eines Clients und Servers sowie zum Signieren und Verschlüsseln von Nachrichten erforderlich sind, die zwischen den beiden gesendet werden." Dies ist definitiv ein großer Vorteil und bietet eine "Fassade", um diese Funktionalität auf nützliche Weise hinzuzufügen. Das Problem besteht darin, dass es sich nicht um ein unterstütztes Produkt handelt, sondern um einen "informellen" Versuch, fehlende Funktionen zu liefern. Außerdem ist es ein wenig einschüchternd für einen Entwickler, da die Lösung auf der erweiterbaren Natur von Formatierern und Kanälen basiert. All dies muss ausgeblendet werden, und die Funktionalität wird durch Hinzufügen eines Eintrags zur Remoting-Konfiguration angezeigt, der beispielsweise die Verwendung von Windows NT Challenge/Response (NTLM) darstellt. Es ist jedoch wahrscheinlich, dass solche Sicherheitsmechanismen in eine zukünftige Version von .NET Remoting integriert werden.

Ein Systemdienst muss auch skalierbar und wieder verfügbar sein, um als Remotingserver nützlich zu sein, da diese Features in einer mehrstufigen verteilten Anwendung erforderlich sind. Ohne IIS müsste der Hostingdienst beispielsweise seine eigene Überwachung und Autorisierung verwalten, die beide standardmäßig mit IIS enthalten sind.

Aus diesen Gründen ist der Hostmechanismus des Systemdiensts von begrenztem Nutzen, z. B. in einer eingeschränkten Umgebung, in der Nachrichten an einem einzelnen Austausch in die Warteschlange gestellt werden, sicherheit kein Problem ist oder IPSec über TCP verfügbar ist.

Enterprise Services Management

Damit eine Remotekomponente an einer COM+-Umgebung teilnehmen kann (und in einem COM+-Kontext ausgeführt wird), muss sie von ServicedComponent erben. ServicedComponent ermöglicht zusammen mit anderen Funktionen, die im System.EnterpriseServices-Namespace bereitgestellt werden, einer CLR-Komponente, eine Reihe von COM+-Attributen anzugeben, z. B. solche, die Transaktionsanforderungen und Serverprozessausführungsattribute angeben. Zusammen mit der starken Benennung und der Verwendung des Befehls regsvcs kann eine Remotekomponente Teil der allgemeinen COM+-Umgebung sein.

Da eine Remotekomponente von MarshalByRefObject erben muss und eine COM+-Komponente von ServicedComponent erben muss (und wir in verwaltetem .NET-Code keine mehrfache Vererbung haben), wie wird dies erreicht? Glücklicherweise wird ServicedComponent von ContextBoundObject abgeleitet, das von unserem erforderlichen MarshalByRefObject abgeleitet ist. Das Erstellen einer COM+-Integration direkt auf Remoting ist also durchaus möglich und bietet die offensichtlichen Vorteile, die von Enterprise Services bereitgestellt werden, z. B. Objektpooling, Unterstützung verteilter Transaktionen und rollenbasierte Sicherheit. Es fehlen jedoch gute Beispiele dafür, wie dies zu tun ist und wie ein solcher Ansatz architektonisch hinsichtlich der Zukünftigen Proofing gestapelt wird.

Es wäre sinnvoll zu erwarten, dass die COM+-Kontextinfrastruktur und die Remotingkontextinfrastruktur im Laufe der Zeit näher zusammenrücken. Wann und wie genau das geschieht, ist zum gegenwärtigen Zeitpunkt unklar.

Bewährte Methoden für die Verwendung von Remoting

Wie immer sind das Entwickeln und Testen verteilter Komponenten nicht ohne damit verbundene Projektkosten und Entwicklerkopfschmerzen. Die folgenden Richtlinien stellen Informationen dar, die auf die harte Art und Weise gelernt wurden.

Erste Schritte

Der Artikel Grundlegende Remoting-Aufgabenliste bietet einen guten Ausgangspunkt für eine Checkliste der Aufgaben, die beim erstmaligen Einrichten von Remoting ausgeführt werden müssen. Es wäre eine gute Idee, den obigen Artikel als Referenzmaterial zu verwenden, wenn sie den Prozess durchlaufen. Im Folgenden finden Sie eine kurze Zusammenfassung der Schritte, die Sie ausführen müssen:

Aufgaben zu Hosts

  • Entwerfen Sie den Dienst, indem Sie App-Domäne, Aktivierungsmodell, Kanal, Port und Veröffentlichung auswählen.
  • Implementieren Sie die Remoting-Host-App-Domäne (z. B. IIS/Systemdienst).
  • Konfigurieren Sie die Einstellungen für die Hostaktivierung, den Kanal und das Protokoll. Es wird empfohlen, eine Konfigurationsdatei zu verwenden, die Sie laden, indem Sie RemotingConfiguration.Configure aufrufen.
  • Veröffentlichen Sie Ihre Schnittstelle für die Clientverwendung (weitere Informationen finden Sie im Abschnitt "Optionen zur Schnittstellenveröffentlichung").

Clientaufgaben

  • Entwerfen Sie den Client, der die App-Domäne und den Aktivierungsmodus auswählt.
  • Überlegen Sie, ob Sie einen Channel und einen Anschluss registrieren müssen.
  • Rufen Sie die Metadaten für Remotetypen ab.
  • Implementieren Sie die Clientanwendungsdomäne.
  • Konfigurieren Sie den Clientaktivierungsmodus und andere Typinformationen, z. B. den Anwendungsnamen, den Kanal und den Objekt-URI. Es wird empfohlen, eine Konfigurationsdatei zu verwenden, die Sie laden, indem Sie RemotingConfiguration.Configure aufrufen.

Formatierungsoptionen

Standardmäßig kann Remoting so konfiguriert werden, dass entweder ein SOAP- oder binärformatierer über einen HTTP-Kanal oder ein binärer Formatierer über einen TCP-Kanal verwendet wird. Diese Konfiguration erfolgt in der Regel, indem die entsprechenden Einträge in der Clientkonfigurationsdatei erstellt und die statische RemotingConfiguration.Configure-Methode aufgerufen wird.

Wenn Sie z. B. eine Remotingverbindung für die Verwendung eines binären Formatierers über HTTP konfigurieren möchten, wird ein Konfigurationseintrag wie folgt erstellt:

<channel ref="http" useDefaultCredentials="true" port="0">
  <clientProviders>
    <formatter ref="binary"/>
  </clientProviders>
</channel>

Hier identifiziert die "Kanalreferenz" das HTTP-Protokoll und die "Formatiererreferenz" das Nachrichtenformat, das über den Kanal gesendet werden soll, in diesem Fall binär.

Leider hat die Verwendung eines binären Formatierers mit einem HTTP-Kanal während der Entwicklung den unerwünschten Nebeneffekt, dass serverseitige Fehler maskiert werden. Beispielsweise wird ein allgemeiner Serverfehler oder eine Zugriffsverletzung dem Client falsch gemeldet. Dies liegt daran, dass die clientseitige Remoting-Komponente bei Verwendung eines binären Formatierers erwartet, dass eine Nachricht im Binärformat zurückgegeben wird. Nur-Text-Fehlerergebnisse werden nicht richtig interpretiert und wie folgt gemeldet:

Eine nicht behandelte Ausnahme vom Typ 'System.Runtime.Serialization. SerializationException' ist in mscorlib.dll aufgetreten. Zusätzliche Informationen: BinaryFormatter Version Inkompatibilität. Erwartete Version 1.0. Version 1008738336.1684104552 erhalten.

Dieser Fehler ist fast immer nicht auf Versionsinkompatibilität zurückzuführen, sondern auf eine Unfähigkeit, Textfehlerantworten auf dem Client zu analysieren. Obwohl erwartet wird, dass dieser Protokollmangel in zukünftigen Versionen des Produkts behoben wird, wird dringend empfohlen, dass der SOAP-Formatierer während des Entwicklungszyklus verwendet wird. Nach dem Nachweis kann der Formatierer aus Leistungsgründen auf binär umgestellt werden, obwohl dies nur dann erfolgen sollte, wenn die Leistung erheblich und erforderlich ist.

Schnittstellenveröffentlichungsoptionen

Nachdem der Remotingserver entworfen und erstellt wurde, muss die bereitgestellte Schnittstelle für die Clientnutzung veröffentlicht werden, um Kompilierzeitverweise aufzulösen und die Erstellung dynamischer Proxyobjekte zu ermöglichen. Es gibt eine Reihe von Möglichkeiten, die es wert sind, dies hier zu wiederholen. Zunächst jedoch ein paar Erinnerungen:

  • Statische Felder und Methoden werden nie entfernt, .NET Remoting befasst sich immer mit instance Membern irgendeiner Form.
  • Private Methoden/Typen können nicht entfernt werden.
  • MarshalByRef-Typen werden nach Verweis entfernt, serialisierbare Typen werden wertkopiert, und Code wird im Clientprozess ausgeführt.
  • Virtuelle Objektmethoden Equals, GetHashCode, MemberwiseClone usw. werden lokal ausgeführt.

Mit diesen Design-Einschränkungen sind die Optionen für die Veröffentlichung einer schnittstelle, die von einem Remoting-Server exportiert wird, wie folgt:

  • Stellen Sie die serverseitige Assembly für Clients zur Verwendung zur Kompilierzeit bereit. Dies wird nicht empfohlen und ist nicht erforderlich, da nur die Schnittstelle und nicht die Implementierung erforderlich ist.
  • Für SOAP-/HTTP-Clients (hier funktioniert unser Remoting-Server als Webdienst, obwohl dies leider eher zur Verwirrung als zur Klärung dient) kann der Remoting-Server eine WSDL-Datei (Web Services Description Language) bereitstellen, die das Serverobjekt und seine Methoden beschreibt. Das SOAPSUDS-Hilfsprogramm, das im Lieferumfang des .NET Framework SDK enthalten ist, kann verwendet werden, um diese WSDL-Dateien als Metadaten zu generieren. Dieser Ansatz eignet sich wirklich besser für einen Webdienst (im strengen Asmx-Sinne) als für Remoting, da die WSDL für eine Remoting-Schnittstelle nicht streng mit dem eines Webdiensts kompatibel ist. In der *.NET Framework Tools*-Dokumentation zum Soapsuds-Tool wird das Soapsuds-Hilfsprogramm ausführlich beschrieben.
  • Deklarieren Sie eine Schnittstelle in einer separaten Bibliothek, und stellen Sie diese Bibliothek mit dem Client bereit. Veröffentlichen Sie eine Serverklasse, die die Schnittstelle implementiert, und der Client kann sie verwenden, indem Sie einen Proxy für die implementierte Schnittstelle abrufen. Dies ist eine sehr sauber Entwurfsentscheidung, da gerade die Schnittstelle von Interesse ist. Dieser Ansatz kann nur für vom Server aktivierte Objekte verwendet werden (siehe Abschnitt Produktfeatures), da keine instance einer Schnittstelle erstellt werden kann.
  • Verwenden Sie SOAPSUDS, um eine Einstandsklasse für den Client zu erstellen, der als Metadaten dienen soll. Sie können SOAPSUDS für Ihre Remoting-Serverassembly ausführen und entweder eine Ausgabeassembly generieren, die direkt als Metadaten verwendet werden kann, oder eine Quelldatei, die direkt in Ihrer Anwendung enthalten sein kann. Dieser Mechanismus ist nützlich für das Erstellen von Anwendungen mit mehreren Ebenen, in denen Objekte in einer Ebene auf Remoteobjekte auf einer anderen Ebene zugreifen möchten. Dieser Ansatz ist interessant und wird in der mehrstufigen Anwendung verwendet, auf die oben im Abschnitt "Einführung" verwiesen wird.

Angenommen, im folgenden Ordner ist ein Befehlsfenster geöffnet:

$FRAMEWORKSDK\Samples\Technologies\Remoting\Basic\RemotingHello\Service

Wir können schreiben: soapsuds -id:. -types:Hello.HelloService,Hello -oa:HelloInterface.dll

Dadurch wird eine Ausgabeassembly HelloInterface.dll erstellt, die nur Metadaten enthält, die auf dem Remotingserver Hello.HelloService basieren, der sich in der Hello-Assembly im aktuellen Verzeichnis befindet. Diese Assembly kann dann direkt vom Client verwendet werden. Der Remotingserverspeicherort wird basierend auf den zur Laufzeit bereitgestellten Konfigurationsdaten gemäß der Remoting-Standardkonfiguration abgeleitet. Die für die Clientassembly erstellte MSIL

ldfld-Objekt [System.Runtime.Remoting]System.Runtime.Remoting.Services.RemotingClientProxy::_tp

zeigt deutlich, dass wir nicht die Remoting-Serverimplementierung verwenden, sondern die Proxyklasse, die mithilfe der von SOAPSUDS erzeugten Metadaten erstellt wurde.

SOAPSUDS wird nicht garantiert/unterstützt, um mit binärer Formatierung zu arbeiten. Es bettet einige SOAP-spezifische "Sachen" in die Metadaten der Ausgabeassembly ein.

Die Empfehlung besteht darin, die Remoting-Schnittstelle so einfach wie möglich zu halten. Verwenden Sie "chunky" im Vergleich zu "chatty"-Schnittstellen, d. h. versuchen Sie, die Anzahl von Remoteanrufen in Ihrem Entwurf zu begrenzen. dies kann in einigen Situationen auch die Übergabe redundanter Parameter beinhalten. Behalten Sie die Remoteschnittstelle in einer separaten Klasse von der tatsächlichen Implementierung bei. Dies ermöglicht ein Muster vom Typ "Fassade", bei dem die Remotingschicht auf Wunsch leicht durch eine andere Technologie ersetzt werden kann.

Verwalten von Fehlern

In diesem Abschnitt werden eine Reihe möglicher Fehlerszenarien beschrieben, die während der Entwicklung (und Verwendung) einer Remoting-Lösung auftreten können. In allen Fällen ist zu beachten, dass die Standardinstrumentierungs- und Überwachungspraktiken weiterhin gelten. Ereignisprotokolle sind nach wie vor eine wertvolle Informationsquelle, ebenso tools wie Network Monitor. Der Netzwerkmonitor kann insbesondere verwendet werden, um Client-/Server-Remoting-Unterhaltungen detailliert anzuzeigen. Remotingserver der mittleren Ebene können weiterhin mithilfe der standardmäßigen Debugtools von Visual Studio .NET gedebuggt werden. Wenn beispielsweise ein Remotingserver von IIS gehostet wird, können Haltepunkte festgelegt werden (die Quelle ist verfügbar), indem die Debugsitzung an den ASP.NET Workerprozess (Visual Studio .Net | Debuggen | Prozesse | Anfügen). Remoting bringt jedoch einen eigenen eindeutigen Satz von Fehlern mit sich, von denen einige unten aufgeführt sind. Beachten Sie, dass alle Fehler mit Versionen des Basic Remoting Hello Sample reproduziert wurden, das mit dem .NET Framework SDK bereitgestellt wurde. Server und Client wurden auf einem einzelnen Computer ausgeführt. Die Symptome sind bei Netzwerklinks identisch, dauern aber erheblich länger, bis ein Fehler basierend auf http/TCP-Timeouteinstellungen auftritt.

Fehlendes MarshalByRef

Für Remoting durch Verweis auf die Arbeit für eine bestimmte Klasse muss diese Klasse nur eine Sache und nur eine Sache tun, und das ist, um von MarshalByRefObject zu erben. Angenommen, der Entwickler hat dies vergessen. Wir erhalten eine Ausnahme vom Typ System.Runtime.Remoting.RemotingException , die besagt, dass wir ein "Missing MarshalByReference" haben.

Ob diese RemotingException ordnungsgemäß abgefangen und behandelt wird, hängt vom Programmierer ab. (Denken Sie daran, dass dieser Entwickler die eine Sache vergessen hat, an die er sich erinnern musste.)

Die Auflösung besteht darin, sich daran zu erinnern, von MarshalByRefObject zu erben!

Falscher Serverendpunkt für die bekannte Serveraktivierung

Für die Serveraktivierung (siehe Abschnitt Produktfeatures) deklariert der Remotingserver den Endpunkt, an dem er lauscht. Dieser Endpunkt umfasst in der Regel einen Objekt-URI (der bekannte Name des Remoteobjekts), ein Protokoll und eine Portnummer. All dies kann natürlich falsch konfiguriert werden.

Ungültiger URI

Der URI für das vom Dienst bereitgestellte Basic Remoting Hello Sample ist HelloService.soap, wie in der zugehörigen web.config-Datei angegeben:

<configuration>
  <system.runtime.remoting>
    <application>
      <service>
        <wellknown mode="SingleCall" type="Hello.HelloService, Hello"
                   objectUri="HelloService.soap" />
      </service>
    </application>
  </system.runtime.remoting>
</configuration>

Dieser Dienst wird von IIS gehostet. Iis-Hosting erfordert, dass der URI entweder durch ".rem" oder ".soap" suffixiert wird. Verwenden Wir .rope auf dem Server. In diesem instance erhalten wir dieses Mal erneut eine RemotingException mit dem Text "Object </Hello.soap> wurde getrennt oder ist nicht auf dem Server vorhanden".

Stellen Sie sicher, dass die URIs übereinstimmen! Stellen Sie außerdem sicher, dass die URIs beim Hosten des Remotingservers in REM oder SOAP enden.

Nicht übereinstimmende Protokoll/Port

Für diesen Test wechseln wir zu einem von der Konsole gehosteten Server, dessen Konfigurationsdatei wie folgt lautet:

<configuration>
  <system.runtime.remoting>
    <application name="RemotingHello">
      <service>
        <wellknown mode="SingleCall" type="Hello.HelloService, Hello"
                   objectUri="HelloService.soap" />
      </service>
      <channels>
        <channel ref="http" port="8000" />
      </channels>
    </application>
  </system.runtime.remoting>
</configuration>

Angenommen, wir würden das Protokoll auf dem Server in TCP ändern und den Client über HTTP sprechen lassen.

Auch hier erhalten wir eine RemotingException. Dieses Mal lautet der Text "Die zugrunde liegende Verbindung wurde geschlossen: Ein unerwarteter Fehler ist bei einem Empfang aufgetreten".

Wenn der Port falsch ist, wird dieselbe Ausnahme ausgelöst. Der einzige Unterschied besteht darin, dass es etwas länger dauert, bis ein Fehler auftritt. Ports und Protokolle müssen server- und clientübergreifend übereinstimmen.

Fehlender URI

Eine weitere Möglichkeit besteht darin, dass der Remoteserver nicht ausgeführt wird. Beispielsweise wird der Server von IIS gehostet und die virtuelle Anwendung oder die zugehörige Assembly fehlt einfach. Wenn Wir erneut unseren Basic Hello Remoting-Server verwenden, erwarten wir, dass eine virtuelle App, RemotingHello, ausgeführt wird. andernfalls erhalten wir eine nicht behandelte Ausnahme (abhängig vom aufrufenden Code). Dieses Mal lautet die Ausnahme jedoch: "Typ clr:Hello.HelloService, Hello kann nicht geladen werden".

Stellen Sie in diesen Fällen sicher, dass die virtuelle Anwendung ausgeführt wird und dass sich die erforderliche Assembly ordnungsgemäß im zugeordneten Unterordner bin befindet.

Zusammenfassend lässt sich sagen, dass serverdefinierte Endpunkte für die Serveraktivierung ordnungsgemäß auf dem Client verwiesen werden müssen. Dies bedeutet, dass alle Ports, Protokolle und URI-Definitionen übereinstimmen müssen. Dies falsch zu machen, ist allzu einfach. Beispielsweise, wenn der Serverspeicherort wie folgt definiert ist:

<service>
   <wellknown mode="SingleCall" type="Hello.HelloService, Hello" 
              objectUri="HelloService.soap" />
</service>

Die Clienteinstellung muss dann wie folgt sein:

<client url="https://localhost/RemotingHello">
   <wellknown type="Hello.HelloService, Hello" 
              url="https://localhost/RemotingHello/HelloService.soap" />
</client>

wobei die URL die virtuelle IIS-App angibt, die den Remotingdienst hostet, und der Typ den Klassen- und Assemblynamen angibt.

Remoting und ASP.NET-Webdienste

Eines der besten und schlechtesten Dinge am IT-Design ist, dass es so viele Architekturkomponenten gibt, aus denen Sie wählen können. Webdienste und .NET-Remoting passen in diese Kategorie, und es ist manchmal schwierig zu entscheiden, welche Technologie für welchen Zweck verwendet werden soll. Die richtige Antwort ist natürlich, diejenige auszuwählen, die am besten für das zu lösende Problem geeignet ist. Präskriptive Kommentare wie "Immer Webdienste verwenden" oder "Webdienste sind eine Teilmenge von Remoting, damit es trotzdem alles Remoting ist" sind zu vermeiden. In diesem Abschnitt werden diese beiden Technologien in Bezug darauf positioniert, warum die Auswahl einer Technologie anstelle der anderen in einem bestimmten Szenario sinnvoll sein könnte.

ASP.NET Webdienst im Vergleich zu .NET Remoting

Beginnen wir mit einer Definition eines Webdiensts als Dienst, der über das Web verfügbar ist. Keine sehr nützliche Definition? Wir könnten sie als "Adressierbare Verarbeitungseinheit" weiter verfeinern, auf die über SOAP und HTTP zugegriffen wird. Diese Verarbeitungseinheit wird über WSDL beschrieben und kann über UDDI veröffentlicht werden." Dies ist nützlicher, da es dazu dient, einen Webdienst von einem Webserver zu unterscheiden, der HTML zurück an einen Browser sendet. Für den Vergleich mit .NET Remoting konzentrieren wir uns speziell auf die Definition eines Webdiensts im Gegensatz zu einem programmgesteuerten Dienst, der über das Web verfügbar ist. Ein Remotehost, auf den über HTTP von einem Client mit WSDL zugegriffen werden kann, ist beispielsweise gemäß unserer Definition ein Webdienst. Mit dieser Präambel (und einem Schwerpunkt auf der Microsoft ASP.NET-Webdienstimplementierung) sollten wir berücksichtigen, welche Faktoren sollten wir bei der Auswahl eines ASP.NET Webdiensts gegenüber .NET Remoting als "Glueware: in einer verteilten Lösung" berücksichtigen?

Interoperabilität

Eine wiederkehrende Microsoft-Meldung lautet: Wenn Sie Interoperabilität zwischen heterogenen Systemen benötigen, ist ein Webdienstansatz, der offene Standards (SOAP, XML, HTTP) verwendet, die richtige Wahl, und die Verwendung von .NET Remoting ist nie eine Interop-Lösung. Für homogene Systeme, bei denen alle Teilnehmer CLR verwaltet werden, kann .NET Remoting die richtige Wahl sein. Dies ist ein ziemlich breiter Pinsel, aber eine nützliche Unterscheidung. Clients von .NET-Remoteobjekten müssen .NET-Clients sein. Wenn Ihre Funktionalität über das Web (web, hier meine ich Internet) durch lose gekoppelte SOAP-Clients (z. B. einen Unix-Prozess) adressierbar sein muss, sind Webdienste die richtige Wahl. Das Intranet unterliegt natürlich nicht den gleichen Einschränkungen: Alle Clients können .NET-Clients sein, und in dieser Konfiguration ist .NET Remoting nicht ausgeschlossen. Für eine Umgebung, in der sich die mittlere (App)-Ebene hinter einer Firewall befindet und direkt mit der Webebene kommuniziert, kann .NET Remoting weiterhin eine Option sein.

Unterstützung für starke Typen

.NET Remoting unterstützt alle verwalteten Typen, Klassen, Schnittstellen, Enumerationen, Objekte usw. Dies wird häufig als "Rich Type Fidelity" kategorisiert. Ein wichtiger Punkt ist hierbei, dass in Fällen, in denen sowohl Client- als auch Serverkomponenten CLR-verwaltete Objekte sind, die in Anwendungsdomänen ausgeführt werden, die Interoperabilität in Bezug auf Datentypen kein Problem darstellt. Im Wesentlichen haben wir ein System der geschlossenen Welt. Beide Enden der Konversation sind vollständig verstanden, und daher können wir diese Tatsache in Bezug auf die Arten von Daten und Objekten nutzen, die wir für die Kommunikation verwenden.

Wenn wir heterogene Systeme haben, müssen wir die Interoperabilität zwischen diesen Systemen berücksichtigen. . In Bezug auf interoperable Datentypen müssen wir sorgfältig vorgehen. Die Webdienstdatentypdefinition basiert beispielsweise auf XML-Schemadefinitionen (XSD) für Datentypsemantik. Es kann jeder Typ verwendet werden, der mit XSD beschrieben werden kann und der über SOAP interoptiert. Dies schließt jedoch die Verwendung einiger Datentypen aus, z. B. gibt es keine W3C-XSD-Darstellung von zeichenlosen Zeichentypen oder Enumerationen; Sammlungen werden bei unterschiedlichen Webdienstimplementierungen unterschiedlich behandelt, ebenso wie Ausnahmen und Datasets. Ein weiteres Problem besteht darin, dass private Felder und Eigenschaften nicht über Webdienstaufrufe hinweg übergeben werden. Dies sind an sich keine kritischen Fragen, sondern vielmehr Faktoren, die beim Entwerfen und Testen von Systemen berücksichtigt werden müssen, die für die Interoperabilität unterschiedlicher Technologien erforderlich sind; nur weil Sie etwas senden können, bedeutet das nicht, dass Sie es empfangen können.

Wenn die Durchlässigkeit zwischen heterogenen Systemen erforderlich ist, sollte .NET Remoting nicht als aktivierende Technologie betrachtet werden. In einer geschlossenen CLR-verwalteten Lösung kann dies sein.

Zustandsverwaltung

Wir haben bereits die Anzahl der Möglichkeiten gesehen, wie die Zustandsverwaltung mithilfe von .Net Remoting erreicht werden kann, basierend auf den Aktivierungsmodi, die entweder clientaktiviert oder Singleton sind. Die Verwaltung des Clientverbindungsstatus über HTTP (ein zustandsloses Protokoll mit unbegrenztem Timeout) wäre sowohl für .NET-Remoting als auch für Webdienste nicht trivial und unpraktisch. Wenn Sie jedoch den Zustand beibehalten müssen, bietet Remoting eine Lösung auf Objektbasis. Webdienste bieten diese clientspezifische Verbindungsstatusverwaltung nicht an. Sie bieten jedoch weiterhin Zugriff auf die ASP.NET Sitzungs- und Anwendungsobjekte.

Verwaltung der Lebensdauer

Im Zusammenhang mit der Zustandsverwaltung ist die Lebensdauerverwaltung. Remoting bietet, wie wir gesehen haben, einen funktionsreichen Mechanismus zum Verwalten der Lebensdauer des Remoteobjekts. Webdienstobjekte kommen und gehen mit dem Webdienstaufruf ein (dies ist sowohl konzeptionell für die Synchronisierung als auch für die asynchrone Synchronisierung der Fall). In dieser Hinsicht funktionieren Webdienste dann als einzelne Aufruftypen in Bezug auf Remoting. Remoting bietet eine viel bessere Kontrolle über die Aktivierung und Beendigung des Remoteobjekts. Dies kann für Ihren Entwurf von Interesse sein oder auch nicht.

Call by Value vs. Call by Reference

An Webdienstaufrufe übergebene Objekte werden serialisiert und nach Wert übergeben. Objekte, die an Remoting übergeben werden, oder die aufgerufenen Objekte selbst können als Wert oder verweis übergeben werden. Serialisierte Remoteobjektmethoden werden auf dem Client verarbeitet. Diese semantischen Unterschiede sollten bei der Auswahl zwischen Remoting und Webdiensten berücksichtigt werden. Auch hier hängt es von der Art des gelösten Problems ab, ob diese Überlegungen für Sie wichtig sind.

Unterstützte Protokolle

Webdienstaufrufe sind auf SOAP-codiertes XML über HTTP beschränkt. Remoting kann TCP-Transporte verwenden, oder die Infrastruktur kann erweitert werden, um benutzerdefinierte Protokolle zu unterstützen. Beispielsweise ist eine Implementierung von Remoting mit Named Pipes unter www.gotdotnet.com im Abschnitt jhawk-Benutzerbeispiele verfügbar.

Hier sehen Sie einen Codeausschnitt aus der NamedPipe-Infodatei , der die erweiterbare Natur von Remoting veranschaulicht:

Der Kanal wird mithilfe der pluggable Channel-Architektur in .NET Remoting eingebunden, indem die IChannel*-Schnittstellen implementiert werden.

Der Named Pipes-Kanal unterstützt die folgenden Features:

* Kommunikation über Named Pipes

* Synchrone Nachrichten

* Asynchrone Nachrichten

* Unidirektionale Nachrichten

*Rückrufe

* Kanalsenken

* Kanaleigenschaften

* Automatische Generierung von Pipenamen'

Wenn Sie also Named Pipes benötigen, bietet Remoting eine Lösung. Erneut wird diese Lösung jedoch (wie bei der SSPI NTLM-Authentifizierungslösung) derzeit nicht von Microsoft unterstützt. Es ist wahrscheinlich, dass Microsoft diese Anforderung zu einem späteren Zeitpunkt erfüllt.

Leistung

Wenn die Leistung wirklich ein hauptanliegend für Ihren Entwurf ist, bietet Remoting über TCP mithilfe eines binären Nachrichtenformats einige erhebliche Leistungsvorteile. Eine vollständige Beschreibung der Umgebung, die zum Erzeugen der in diesem Artikel beschriebenen Ergebnisse verwendet wird, und des Tests selbst finden Sie im Artikel Leistungsvergleich: .NET Remoting vs. ASP.NET Webdienste

Hier sind einige zusammengefasste Leistungsstatistiken aus diesem Artikel:

Legende: ASMX – Webdienst, alle anderen darstellen Remoting-Lösungen
WS bezeichnet einen Windows-Dienst, der die Remotekomponente hostet.

Abbildung 1. Performance Statistics

In diesem Artikel werden die Leistungszahlen wie folgt erläutert:

"WS_TCP_Binary, wie oben gezeigt, in dem das Objekt für die Verwendung des TCP-Kanals und des Binärformatierers konfiguriert ist, wobei der Host ein Windows-Dienst ist, übertrifft andere Verteilungstechniken. Der Grund dafür ist, dass bei diesem Ansatz Binärdaten über unformatierte TCP-Sockets übertragen werden, die effizienter als HTTP sind. und da die Daten nicht codiert/decodiert werden müssen, entsteht weniger Verarbeitungsaufwand. Wir sehen eine Leistungsspanne von etwa 60 % zwischen WS_TCP_Binary und dem langsamsten Ansatz.

Obwohl IIS_HTTP_Binary die gleiche binäre Nutzlast wie WS_HTTP_Binary erzeugt, ist es langsamer, da es einen zusätzlichen Prozesshop von IIS (Inetinfo.exe) zu Aspnet_wp.exe gibt. Der gleiche Grund erklärt den Leistungsunterschied zwischen IIS_HTTP_SOAP und WS_HTTP_SOAP.

WS_HTTP_Binary und WS_TCP_SOAP bieten eine sehr ähnliche Leistung. Obwohl erstere den zusätzlichen Mehraufwand für die ANALYSE von HTTP hat, und letzteres den zusätzlichen Mehraufwand für die Analyse von SOAP hat, scheint es, dass der Mehraufwand der HTTP-Analyse und SOAP-Analyse in diesem Fall ungefähr gleich ist.

Der ASP.NET-Webdienst übertrifft IIS_HTTP_SOAP und WS_HTTP_SOAP, da ASP.NET XML-Serialisierung effizienter ist als die SOAP-Serialisierung von .NET Remoting. Und wie oben zu sehen ist, ist der ASP.NET-Webdienst IIS_HTTP_Binary sehr ähnlich."

Wenn die Rohgeschwindigkeit wirklich von entscheidender Bedeutung ist, kann diese "60%ige Leistungsverteilung" erheblich sein. Der Nachteil ist die Notwendigkeit, den Server in einem Windows-Dienst zu hosten, um das TCP-Protokoll zu verwenden (siehe vorherigen Abschnitt über Remotehosting). Effektiv wird die Sicherheit für die Leistung abgetauscht, und als Ansatz wird "nicht über das Internet oder ein nicht sicheres Intranet empfohlen".

Zusammenfassung

ASP.NET Webdienste sind XML-basiert, für praktische Zwecke, die die Verwendung von HTTP erfordern (da sie vom IIS gehostet werden), und bieten ein einfaches Programmiermodell und eine starke plattformübergreifende Unterstützung. Sie sorgen für ein gewisses Maß an Erweiterbarkeit durch die Verwendung von SoapExtensions, z. B. die Verschlüsselung des Datenstroms. Remoting verfügt über ein komplexeres Programmiermodell, bietet jedoch einige klare Vorteile in Bezug auf Typtreue, Zustandsverwaltung und Erweiterbarkeit, sowohl in Bezug auf Protokolle als auch Nachrichtenformate. Remoting kann nicht für non-.NET Clients verwendet werden, sodass eine direkte Internetclientverbindung zu Remotehostverbindungen nicht möglich ist. Remoting bietet kein Sicherheitsmodell, wenn es außerhalb von IIS gehostet wird. Wenn IIS gehostet wird, bietet Remoting dieselben Sicherheitsfeatures wie ASP.NET, einschließlich der Verwendung sicherer Protokolle wie SSL. Wenn die Interoperabilität mit anderen Plattformen keine Rolle spielt und sowohl die Client- als auch die Serverkonfiguration unter Ihrer vollständigen Kontrolle stehen, sollten Sie .NET Remoting in Betracht ziehen. Wenn Sie Remoting verwenden, bevorzugen Sie das IIS-Hosting mithilfe des HTTP-Kanals dem Nicht-IIS-Hosting, um von der zugehörigen Sicherheits- und Skalierbarkeitsinfrastruktur zu profitieren. Dies bedeutet natürlich, dass Sie in der Lage sein müssen, IIS in Ihrer Lösung zu beauftragen. Wenn dies nicht möglich ist, kann Remoting eine zu mühsame Aufgabe sein, um sie zu übernehmen; dies hängt von der Art des gelösten Problems ab. Da .NET Remoting einen .NET-Client erfordert, ist es sinnvoll, den schnellsten verfügbaren Formatierer zu verwenden. Wählen Sie also Binärdatei vor SOAP aus, da dies zu einer besseren Leistung führt. Beachten Sie den obigen Vorschlag im Abschnitt Bewährte Methoden, dass dieser Formatierer zur Releasezeit und nicht während der Entwicklung angewendet wird.

Kurzfassung

.NET Remoting ist ein nützliches Tool, das in bestimmten Arten von verteilten Lösungen verwendet werden kann. Es bietet ein erweiterbares Modell in Bezug auf die Protokolle und Nachrichtenformate, die es unterstützen kann, und kann in bestimmten Szenarien Leistungsvorteile bieten. Es sollte nicht direkt im Internet bereitgestellt werden, und seine Serverobjekte sollten unter IIS gehostet werden, um von den Sicherheits- und Leistungsfeatures zu profitieren, die IIS für Prozesse bietet, die unter seiner Kontrolle ausgeführt werden.

Remoting sollte für verteilte Lösungen in der geschlossenen Welt berücksichtigt werden, bei denen sowohl Client als auch Server CLR-verwaltete Prozesse sind. Beispiele sind eine Komponente auf einer beliebigen Ebene innerhalb einer Intranetlösung, entweder über einen sicheren TCP-Kanal wie IPSec oder über HTTP oder als Anwendungskomponente der mittleren Ebene, die mit einer .NET-Webebenenkomponente über eine Firewall kommuniziert. in diesem Fall sollte der HTTP-Kanal mit dem Binärformatierer ausgewählt werden, nachdem die Lösung mithilfe des SOAP-Formatierungsprogramms nachgewiesen wurde.

Für Systeme, die mit Nicht-CLR-Clients zusammenarbeiten müssen, verwenden Sie ASMX-Webdienste, um einige der Fallstricke in Bezug auf Datentypen zu vermeiden (siehe Abschnitt zur Unterstützung von starken Typen).

Beachten Sie, dass das Hosten außerhalb von IIS mit TCP Leistungsvorteile mit sich bringt, aber auf Kosten der Anforderung benutzerdefinierter Sicherheit.

Entwurf und Implementierung

Die Implementierung und Konfiguration von Remoting ist ein relativ einfacher Prozess. Die Auswahl des Remotinghosts, des Protokolls und des Aktivierungsmodells sollte die erste Aufgabe im Prozess sein. Halten Sie den Entwurf und die Implementierung so einfach wie möglich, und überlegen Sie sich genau, welcher Mechanismus für die Veröffentlichung von Schnittstellen für Ihre Lösung am sinnvollsten ist. Der empfohlene Ansatz besteht darin, die Schnittstelle nur zu veröffentlichen, da dies das sauberste konzeptionelle Modell ist. dies schließt jedoch die Verwendung clientaktivierter Objekte aus. Debugger, Ereignisprotokolle und Netzwerkmonitor sind alle nützlichen Tools während des Entwicklungsprozesses, und alle können bei der Entwicklung von Remotekomponenten verwendet werden.

Zukunft des Remotings

Fragen wie wann Remoting oder wann Webdienste verwendet werden sollen, sind schwierige Fragen, die durch die mangelnde Klarheit in Bezug auf die Definition von Begriffen verstärkt werden. Beispielsweise ist die Definition eines Webdiensts unklar, und Remoting kann so konfiguriert werden, dass es als Webdienst funktioniert.

Es ist wahrscheinlich, dass remoting- und ASMX-Technologien in Zukunft enger zusammengeführt werden. Im Moment haben wir jedoch zumindest ein vernünftiges Bild davon, wann wir welche Technologie verwenden müssen, wie oben beschrieben.

Der Schwerpunkt der Entwicklung liegt derzeit auf der Bereitstellung von GXA-Implementierungen für Routing, Sicherheit und Transaktionsunterstützung. Diese Unterstützung basiert auf der Verwendung von SOAP-Headern und zielt derzeit direkt auf die Erweiterung der Funktionalität von Webdiensten ab. Während GXA .NET Remoting nicht im klassischen Sinne behandelt, wie in diesem Artikel beschrieben, behandelt es viele der Probleme, für die Remoting verwendet werden würde, z. B. Zustands- und Transaktionsverwaltung. Obwohl die derzeitige GXA-Implementierung darauf abzielt, viele der Probleme zu lösen, mit denen Webdienste konfrontiert sind, ist sie grundsätzlich darauf ausgerichtet, diese Probleme so technologisch agnostisch wie möglich zu lösen. Es wird interessant sein, die Auswirkungen zu sehen, die die Entwicklung von GXA sowohl auf Webdienste als auch auf .Net Remoting hat.

Zusätzliche Ressourcen