Bonn-to-code.net Die AppDomain Das unbekannte Wesen? 19.11.2013 Dr. Jochen Manns...

Post on 06-Apr-2015

105 views 1 download

transcript

bonn-to-code.netbonn-to-code.netbonn-to-code.netbonn-to-code.net

Die AppDomainDas unbekannte Wesen?

Die AppDomainDas unbekannte Wesen?

19.11.2013

Dr. Jochen Manns

EMail: dev-1@psimarron.netWebsite: http://www.jochen.jochen-manns.de

bonn-to-code.netbonn-to-code.net

AgendaAgenda

Kleine Einführung AppDomains und die Anwendung Varianten von Marshalling

Marshalling in der Praxis By Value By Reference It depends…

bonn-to-code.netbonn-to-code.net

ÜbersichtÜbersicht

bonn-to-code.netbonn-to-code.net

.NET und die AppDomain.NET und die AppDomain

Jeder Code läuft in einer AppDomain Threads sind ein orthogonales Konzept

Mindestens eine AppDomain pro Prozess Default AppDomain wird beim Starten

angelegt Weitere müssen explizit erzeugt werden

Im Normallfall unsichtbar Nur die Default AppDomain Keine Notwendigkeit, AppDomains zu

kennen

bonn-to-code.netbonn-to-code.net

Warum benutzt man AppDomains?Warum benutzt man AppDomains?

Eine Art Prozess im Windows Prozess In .NET hochgradig isoliert

Nativer Code kennt keine Grenzen Eigene Sicherheitsregel

Vor allem Ausführungspfade für Bibliotheken

Erweiterungskonzepte / PlugIns Sichere, abgeschirmte Umgebung der

PlugIns Kontrollierte Schnittstelle zum Host

Zeitweises Laden von Bibliotheken

bonn-to-code.netbonn-to-code.net

ASP.NET und IISASP.NET und IIS

Ein Prozess pro Application Pool Eine AppDomain pro virtuellem

Verzeichnis Mehrere virtuelle Verzeichnisse pro Pool Trotzdem vollständig isoliert (.NET)

ASP.NET Hosting ApplicationHost Klasse Volle ASP.NET Laufzeitumgebung

Web.Config, WebApi, MVC, ASPX, ASMX, … Separate AppDomain für den Host

bonn-to-code.netbonn-to-code.net

KommunikationKommunikation

bonn-to-code.netbonn-to-code.net

Kommunikation und MarshallingKommunikation und Marshalling

Isolation kontrolliert durchbrechen Proxy / Stub Objekte

Proxy in der steuernden AppDomain (Host) Stub in der untergeordnete AppDomain

Inter-AppDomain Methodenaufrufe AppDomain Wechsel auf einem einzigen

Thread Indirekte Aufrufe kosten Zeit

Was ist aber mit Daten / Objekten? Marshalling in zwei Varianten

bonn-to-code.netbonn-to-code.net

Marshal By ValueMarshal By Value

Vollständige Übertragung Keine Kommunikation über die Daten Hohe Unabhängigkeit der AppDomains Datenaustausch, evtl. umfangreich

[Serializable] Binäre Variante Berücksichtigt alle .NET Fields

[NonSerialized]

Zwingend für alle referenzierten Objekte

bonn-to-code.netbonn-to-code.net

Marshal By ReferenceMarshal By Reference

Proxy Referenz auf einen Stub Keine Datenübertragung Zugriff erfordern erneuten AppDomain

Wechsel Jede Codeausführung (auch der Abruf

eines .NET Fields) erfolgt in der AppDomain, in der das Objekt erzeugt wurde

Im By Value Fall wird Code immer in der AppDomain des Aufrufers ausgeführt

Ableiten von MarshalByRefObject

bonn-to-code.netbonn-to-code.net

Böse Falle Garbage CollectionBöse Falle Garbage Collection

Ein Proxy ist keine starke Referenz Der Stub muss sich vor Freigabe

schützen InitializeLifetimeService Ansonsten ist der Proxy irgendwann kaputt

bonn-to-code.netbonn-to-code.net

ASP.NET HostingASP.NET Hosting

bonn-to-code.netbonn-to-code.net

WebApi Hosting in einem DienstWebApi Hosting in einem Dienst

Datenverwaltung im Dienst Datenbank Steuerungslogik Kontrollierte Laufzeitumgebung

Remote Schnittstelle für Clients WCF WebApi Self Hosting ASP.NET Hosting

Für REST, aber auch ASPX, ASMX, … Betriebssicherheit durch Isolation

bonn-to-code.netbonn-to-code.net

Zugriff auf die Dienst AppDomainZugriff auf die Dienst AppDomain

ASP.HET Hosting über Proxy / Stub Dienst kann auf ASP.NET Laufzeit zugreifen

Sequenz immer ähnlichm_Runtime = (IASPNETProxy) ApplicationHost.CreateApplicationHost( typeof( ASPNETProxy), … );m_Runtime.SetServer( m_Server );

Dienstobjekt in ASP.NET verfügbar machen By Reference Stub lebt im Dienst Proxy kann von ASP.NET angesprochen

werden

bonn-to-code.netbonn-to-code.net

MarshallingMarshalling

bonn-to-code.netbonn-to-code.net

REST via Marshal By ReferenceREST via Marshal By Reference

[DataContract]public class ClientResponse{ [DataMember] public string Data { get; set; }}

var response = new ClientResponse { Data = proxy.Analyse( 12 ) };

• Die Antwort an den Client wird in der ASP.NET AppDomain erstellt.

• Jeder Aufruf an den Dienstproxy muss die AppDomain Grenze überschreiten.

• Alle Objekte müssen eine Überschreitung zulassen:

• By Value, wie alle einfachen .NET Klassen

• By Reference, üblicherweise eigene Klassen

• Wilder Zugriff führt zu Fehlermeldungen, gute Kontrolle!

• Die Ausführungsgeschwindigkeit kann leiden

• Besondere Vorsicht bei Listen von Objekten

• Viele Einzelzugriffe auf .NET Fields & Properties evtl. problematisch

public interface IServiceProxy { string Analyse( int depth ); }

bonn-to-code.netbonn-to-code.net

REST via Marshal By ValueREST via Marshal By Value

[Serializable]public class ServiceResponse{ public string Data { get; set; }}

var serviceResponse = proxy. Analyse( 12 );

var response = new ClientResponse { Data = serviceResponse.Data };

• Die AppDomain des Dienstes bereitet alles vor

• Die Bearbeitung findet vollständig dort statt

• In der ASP.NET AppDomain wird noch einmal umkopiert• Die Dienst AppDomain kann natürlich auch direkt das Ergebnis erzeugen• Dann muss dieses aber auch By Value sein

[DataContract, Serializable]public class ClientResponse{ [DataMember] public string Data { get; set; }}

public interface IServiceProxy { ServiceResponse Analyse( int depth ); }

public interface IServiceProxy { ClientResponse Analyse( int depth ); }

var response = proxy.Analyse( 12 );

bonn-to-code.netbonn-to-code.net

Code AbhängigkeitenCode Abhängigkeitenusing System;using System.Collections.Generic;using Sample.ClientNamespace;

namespace Sample.ServiceNamespace{ public class ServiceItem { public Service Service { get; private set; }

public string Data { get; private set; }

public ClientItem ToClient() { return new ClientItem { Data = Data }; } }

public class Service : MarshalByRefObject { private readonly List<ServiceItem> m_items = new List<ServiceItem>();

public ClientItem ToClient( int index ) { return m_items[index].ToClient(); } }}

using System;using System.Runtime.Serialization;using Sample.ServiceNamespace;

namespace Sample.ClientNamespace{ [DataContract, Serializable] public class ClientItem { public string Data { get; set; } }

public class TheController { public ClientItem GetItem( int index ) { return ASPNETRuntime.ServiceProxy.ToClient( index ); } }}

bonn-to-code.netbonn-to-code.net

EntkoppelnEntkoppeln

using System;using System.Collections.Generic;

namespace Sample.ServiceNamespace{ public class ServiceItem { public Service Service { get; private set; }

public string Data { get; private set; } }

public class Service : MarshalByRefObject { private readonly List<ServiceItem> m_items = new List<ServiceItem>();

public TClientType ToClient<TClientType>( int index, Func<ServiceItem, TClientType> factory ) { return factory( m_items[index] ); } }}

using System;using System.Runtime.Serialization;using Sample.ServiceNamespace;

namespace Sample.ClientNamespace{ public class TheController { public ClientItem GetItem( int index ) { return ASPNETRuntime.ServiceProxy.ToClient( index, ClientItem.FromService ); } }

[DataContract, Serializable] public class ClientItem { public string Data { get; set; }

public static ClientItem FromService( ServiceItem item ) { return new ClientItem { Data = item.Data }; } }}

Die statische Methode wirdin der AppDomain desDienstes ausgeführt!

bonn-to-code.netbonn-to-code.net

Marshal By Value nach BedarfMarshal By Value nach Bedarf

Mehrere By Value Varianten nutzen Je nach Kontext verschiedene Inhalte Pro REST Controller oder gar pro Methode

Gezielt mischen By Reference für äußere Objekte By Value für Detailobjekte

Querreferenzen können verloren gehen Querreferenzen lassen Datenmenge

explodieren

bonn-to-code.netbonn-to-code.net

ZusammenfassungZusammenfassung

AppDomains sind isolierte Bereiche Innerhalb eines Windows Prozesses

Methoden werden über Proxy Klassen aufgerufen

Daten werden By Value oder By Reference ausgetauscht

Beide Varianten haben Vor- und Nachteile

Hybride führen oft zur besten Lösung

Generische Methoden zur Entkoppelung