Zyan Communication Framework

Rainbird
Hallo zusammen,

angeregt durch die Diskussionen über Event Based Components habe ich ein Framework für verteilte Anwendungen geschrieben, welches auch EBCs unterstützt.

Mit Zyan können Komponenten auf verschiedenen Computern laufen und kommunizieren untereinander übers Netzwerk. Darüber hinaus bietet Zyan Zusatzdienste wie Verschlüsselung, Authentifizierung, Sitzungsverwaltung und automatische Übertragung von verteilten Transaktionen (via System.Transactions). Die Kommunikation kann wahlweise über TCP oder HTTP erfolgen. Sicherheitsfeatures etc. sind individuell einstellbar und können - bei Bedarf - auch leicht abgeschaltet werden. Zyan bietet Schnittstellen zur Erweiterung des Systems an (z.B. für benutzerdefinierte Authentifizierung oder eigene Netzwerkprotokolle).

Es werden natürlich auch klassische Komponenten unterstützt, die nicht nach EBC-Architektur entworfen wurden!

Ihr findet das Projekt zum runterladen, sowie den Quellcode und die Dokumentation (ist noch nicht vollständig, aber wächst fast täglich) unter  http://zyan.codeplex.com/.
Es gibt auch eine kleine Beispielprojektmappe, die an einem sehr einfachen Beispiel zeigt, wie verteilte EBCs mit Zyan funktionieren. Hier geht´s direkt zum Download-Bereich:  http://zyan.codeplex.com/releases

Das Projekt steht unter der MIT Lizenz und kann somit frei für eigene Zwecke verwendet werden. Jegliche Haftung ist allerdings ausgeschlossen!

Über Kommentare, konstruktive Kritik oder Verbesserungsvorschläge würde ich mich sehr freuen. Vorzugsweise direkt unter  http://zyan.codeplex.com/discussions. Wer Bugs findet, kann Sie gerne im Issue Tracker unter  http://zyan.codeplex.com/workitem/list/basic eintragen.
Sebastian.Lange
Zitat:
angeregt durch die Diskussionen über Event Based Components

Welche Diskussionen meinst du ?
Ich kenne nur Ralph Westphals Statements dazu.

Für nicht EBC Kundige macht das auch mit der Doku natürlich alles keinen Sinn.
Vielleicht kann Zyan hier noch etwas Begeisterungsarbeit leisten. :-)
herbivore
Hallo Sebastian.Lange,

Zitat:
Welche Diskussionen meinst du ?

die Diskussionen im Forum:  Forumssuche nach EBC or EBCs (natürlich nur die Threads vor dem 23.09.2010 00:31).

herbivore
Rainbird
Hallo Sebastian.Lange,

Zitat von Sebastian.Lange:
Für nicht EBC Kundige macht das auch mit der Doku natürlich alles keinen Sinn.

Ich bin mit der Zyan-Doku leider noch nicht bei EBCs angekommen. Ich wollte zuerst drin haben, wie man ein verteiltes Hello World mit Zyan zum laufen bringt und wie es grundlegend funktioniert. Ist ja aber auch noch nicht fertig. Ich werde noch ganz ausführlich erklären, wie man verteilte EBC-Style-Anwendungen mit Zyan erstellt.

Die kleine beiliegende Beispiel-Projektmappe ist nur ein mini, mini Demo um das aller grundlegendste zu zeigen.

Zitat von Sebastian.Lange:
Vielleicht kann Zyan hier noch etwas Begeisterungsarbeit leisten. :-)

Das hoffe ich. Es ist allerdings auch ein Test für die Praxistauglichkeit. Ich habe vor ein kleines Mini-CRM-System-Beispielprojekt mit EBCs und Zyan aufzusetzen, um auszuloten, ob EBCs für die erstellung von Buisness-Anwendungen wirklich Vorteile bringen. Alles was es im Netz momentan gibt, geht nicht wirklich über Hello World hinaus. Es muss eine Anwendung her, die zumindest halbwegs Real World-Charakter hat. Zuerst musste die Verteilung von EBCs aber erst mal laufen. Das ist mit der aktuellen Zyan-Version nun geschafft.

Zyan geht bei der Verteilung übrigens einen anderen Weg, als der von Ralf Westphal in seinem Beispiel unter  Remote Communication mit Event-Based Components und Application Space Vorgeschlagene!

Aber selbst ganz ohne EBCs ist Zyan ein nützliches Kommunikations-Framework für einfache und intuitive .NET zu .NET Kommunikation.
Peter Bucher
Salute Rainbird

Ich habe mal deinen Quellcode durchgeschaut.

Die Sache sieht sehr interessant aus. Das du die "normalen" Komponenten dann mit einer Wrapperklasse als "MarshalByRefObject" ausgibt, ist natürlich cool :-).

Von Benutzer, API-Benutzersicht sicherlich mehr als einen Blick wert.

Was mir aber ein wenig missfällt, sind die Kommentare - der Noise - zwischen dem Code, sowie der Gebrauch von Region und folgend, die langen Klassen, die da teilweise vorkommen.

Beispielsweise hast du im ZyanComponentHost in einer Region mit 3, 4 Methoden einen sehr rudimentären "DI-Container" drin, bzw. das Grundstück davon mit Registrierung, Deregistrierung sowie der Ausgabe aller Registrierungen und natürlich das erstellen einer Instanz.
Drin ist auch Singleton. Soweit ich gesehen habe.

Jetzt mal ganz abgesehen von der Komponente an sich, was meinst du zu meinen obigen Kommentaren und wieso nutzt du nicht eine externe Komponente, bzw. nimmst den "ComponentContainer" raus, in eine eigene Klasse?


Gruss Peter
Rainbird
Hallo Peter Bucher,

Zitat von Peter Bucher:
Was mir aber ein wenig missfällt, sind die Kommentare - der Noise - zwischen dem Code, sowie der Gebrauch von Region und folgend, die langen Klassen, die da teilweise vorkommen.

Die Kommentare und Regions sind so gewollt. Ich habe Code-Kommentare in deutschem Klartext sehr schätzen gelernt. Regions finde ich auch sehr praktisch. Aber das ist alles Geschmacksache.
Mit den langen Klassen hast Du allerdings völlig Recht. Die müssen noch Refaktorisiert werden. Vieles ist relativ schnell runtergeschrieben. Ich wollte die Grundfunktionen erstmal am Laufen haben, damit ich den Code veröffentlichen kann. Der Feinschliff kommt dann so nach und nach. Ich bin aber für solche Anregungen sehr dankbar. Das hilft mir, meine Codequalität in diesem Projekt zu steigern.

Zitat von Peter Bucher:
Beispielsweise hast du im ZyanComponentHost in einer Region mit 3, 4 Methoden einen sehr rudimentären "DI-Container" drin, bzw. das Grundstück davon mit Registrierung, Deregistrierung sowie der Ausgabe aller Registrierungen und natürlich das erstellen einer Instanz.
Drin ist auch Singleton. Soweit ich gesehen habe.

Das wird noch entzerrt und soll auch in separate Klassen aufgeteilt werden. Wie gesagt, ich habe zuerst mal alles in den zentralen Kern reingestopft um auch zu testen, ob das alles so funktioniert. Zuerst wird die Sitzungsverwaltung ausgelagert werden, da diese auch noch Schnittstellen für Erweiterungen spendiert bekommt. Momentan sind nur In-Memory-Sessions möglich, was eine große Einschränkung für die Skalierbarkeit ist. Das wird sich ändern. In diesem Zuge wird auch die Sitzungsverwaltung aus dem Kern ausgelagert.

Zitat von Peter Bucher:
... wieso nutzt du nicht eine externe Komponente, bzw. nimmst den "ComponentContainer" raus, in eine eigene Klasse?

Es muss einfach sein. Und zwar in Anwendung, Konfiguration und Deployment. Eiserne Regel für das Zyan-Framwork an sich: Eine einzige DLL!
Ich will noch einen Zyan.Server (EXE) schreiben, der als generischer Host-Prozess verwendet werden kann und Dinge wie Deployment und Monitoring adressiert.

Aber wer möchte, kann ohne Änderungen am Code externe DI-Systeme wie Unity zusammen mit Zyan verwenden. Dafür hat der ZyanComponentHost folgende Methode:

C#-Code:
/// <summary>
/// Registriert eine bestimmte Komponente.
/// </summary>
/// <typeparam name="I">Schnittstellentyp der Komponente</typeparam>
/// <param name="factoryMethod">Delegat auf Fabrikmethode, die sich um die Erzeugung und Inizialisierung der Komponente kümmert</param>
void RegisterComponent<I>(Func<object> factoryMethod);

Du kannst also einfach eine Factory-Methode übergeben, und so das Erstellen der Komponente in eigenen Code auslagern. Auf welche Art und Weise Du dann die Komponenteninstanz erzeugst, ist Dir überlassen.

Ich will auch bei Zeiten noch ein Beispiel schreiben, wie man sowas mit Unity machen kann.
malignate
Hi, ich habe mir auch mal den Code angeschaut:

Was ich am Konzept nicht verstehe: Irgendwie sieht das wie eine Neuentwicklung von WCF aus, zumindest teilsweise.

Warum nicht einfach ein Wrapper über WCF als Schnittstelle zu EBCs und Vereinfachung der Kommunikation?
Rainbird
Hallo malignate,

Zitat von malignate:
Irgendwie sieht das wie eine Neuentwicklung von WCF aus, zumindest teilsweise.

Keineswegs. Es ist vielmehr eine Erweiterung von .NET Remoting.
Ich hatte anfangs gründlich überlegt, ob ich WCF oder .NET Remoting als Basis verwenden soll und habe mich für letztes entschieden.

WCF zwingt einem ein serviceorientiertes Programmiermodell auf. Das ist toll in einem plattformübergreifenden Szenaraio, aber wirft einem für reine .NET zu .NET Kommunikation nur Steine in den Weg. Um meine Entscheidung besser zu verstehen, hier eine Liste der Contra-WCF-Argumente:
  • Bei WCF gibt es keinen Aufrufkontext (CallContext) der implizit Daten über eine Aufrufkette von mehreren Services transportiert.
  • Das Erweiterungsmodell von WCF ist wesentlich komplexer als das von .NET Remoting.
  • WCF unterstützt nicht die schnelle binäre Serialisierung von ADO.NET DataSets (RemotingFormat=Binary; Das hat nicht unbedingt was mit EBCs zu tun, aber ich bin ein großer Anhänger von DataSets und da gefällt es mir natürlich nicht, dass WCF diese nicht optimal unterstützt).
  • Mit WCF kann man keine Objektreferenzen versenden.
  • WCF ist zu starr, da man alles (z.B. Callbacks, Faults) explizit über Kontrakte definieren muss.
  • WCF ist ein Konfigurationsmonster!
  • WCF unterstützt den BinaryFormatter nicht.
  • Bei WCF ziehen sich Attribute wie bei einem durchwachsenen Schinken durch den Code. Ich mochte durchwachsenen Schinken noch nie.
Die durchwachsene Schinken-Geschichte führt in der Praxis dazu, dass man den WCF-Service als Fassade für die eigentliche Geschäftkomponente dahinter verwendet. Das bedeutet dann stumpfsinnig Methodenaufrufe über die Service-Fassade meistens 1:1 durchzureichen. Das macht keinen Spaß.

In besonderem Maße ausschlaggebend war die Tatsache, dass es bei WCF keinen Aufrufkontext gibt. Es gibt nur den OperationContext, der aber nur einen Aufruf weit funktioniert. Wenn ich Aufrufketten habe, wie Client -> Service A -> Service B, dann stehe ich mit WCF im Regen.

Zitat von malignate:
Warum nicht einfach ein Wrapper über WCF als Schnittstelle zu EBCs und Vereinfachung der Kommunikation?

Das ist eine berechtigte Frage.
Mit WCF einfach ein EBC-Zwischenstück zu bauen, welches die Nachricht vom Ausgangspin aufnimmt und diese zum Eingangspin der entfernten Komponente transportiert, klingt zunächst naheliegend. Ralf hat das so ähnlich in seinem Beispiel mit Application Spaces ( Remote Communication mit Event-Based Components und Application Space) aufgebaut. Der Aufbau lässt sich so darstellen:

A<->P...S<->B

A=Komponente A (Geschäftskomponente)
B=Komponente B (Geschäftskomponente)
P=Proxy (Infrastrukturkomponente)
S=Stub (Infrastrukturkomponente)
<->=Verdrahtung
...=Netzwerkübertragung

Damit Komponente A die entfernte Komponente B konsumieren kann, müssen ihre Pins mit einem Proxy verdrahtet werden. Die Pins von Komponente B müssen auf der Serverseite mit einem Stub verdrahtet werden, damit Nachrichten zwischen den beiden fließen können.
Dauraus ergibt sich eine Verdoppelung der zu ziehenden Drähte! Und das bei jeder entfernten Komponente: Immer und immer wieder.
Okay, stumpfsinnige Verdrahtung ist ein Grundproblem von EBCs, war irgendwann durch einen schicken Designer eingedämmt werden soll. Da will ich nicht schon wieder drauf rumreiten.
Viel schlimmer als der erhöhte Verdrahtungsaufwand ist aber die Tatsache, dass ich die Infrastruktur-Zwischenstgücke das Modell verkomplizieren. Ich muss sie mir immer wegdenken, wenn ich meine Geschäftskomponenten zusammenstecke. Da helfen mir auch keine Boards, da ein Boards nicht in zwei Prozessen leben kann.

Ich will nicht A<->P...S<->B denken müssen, sondern ich will eigentlich A<->B denken. Wenn ich verteilte Geschäftskomponenten zusammenstecke, dann möchte ich auf der Abstraktionsebene dieser Geschäftskomponenten verharren. Infrastrukturkomponenten stören dabei. Deshalb müssen sie transparent gemacht werden. Darum kümmert sich Zyan.

Mit Zyan kann ich A<->B denken. Zwar wird im Clientprozess für B auch ein Proxy verwendet, aber der fühlt sich genauso an wie B und muss leider sein, da B nunmal in einem anderen Prozess lebt. Ich verdrahte A mit dem Proxy von B und diese Verdrahtung wird von Zyan autonatisch auf die echte Komponente B angewendet. Also keine verdoppelten Drähte und keine Infrastruktur-Fremdkörper im Modell.

Ich möchte EBCs gerne in der Praxis einsetzen. Damit das funktionieren kann, müssen EBCs einfach und intuitiv einsetzbar sein. Zumindest in verteilten Szenarien sind EBCs mit .NET-Bordmitteln das definitiv nicht. Mit Zyan wird die Verteilung von EBCs dagegen kinderleicht und geht vor allem von Statten, ohne dass man viel Code hinschreiben muss. Zyan selber ist nicht aus EBCs gebaut, aber das .NET Framework und z.B. WCF ja auch nicht Augenzwinkern .

Selbst wenn sich bei meinen Praxistests herausstellt, dass EBCs nicht alltagstauglich sind, war die Mühe Zyan zu schreiben nicht vergebens, denn Zyan kann auch mit ganz klassischen Nicht-EBC-Komponenten ungehen. Dann ist es immer noch einfacher und intuitiver als WCF.
Rainbird
Zitat von Peter Bucher:
... wieso nutzt du nicht eine externe Komponente, bzw. nimmst den "ComponentContainer" raus, in eine eigene Klasse?

Ich hab Deinen Vorschlag aufgegriffen und die Komponentenverwaltung nun als separate Klasse rausgezogen. Das ganze nennt sich jetzt Komponenten-Katalog (ComponentCatalog) und kann auch ganz ohne Verteilung genutzt werden.

Der Ansatz hat sich als sehr vorteilhaft erweisen, da ich so ganz leicht einen Komponenten-Katalog in verschiedenen ZyanComponentHosts mit verschiedenen Protokollen hosten kann.

Neu ist in der  Version 0.8 auch die Unterstützung von zusammensteckbaren Anwendungen im neuen Namensraum Zyan.Communication.Modularity. Die Klasse ZyanApplication fungiert dabei als Stammobjekt und Microkernel. Sie lädt sog. Module (Gruppierung von Assemblies in einem Unterverzeichnis, welches den Modulnamen darstellt). Module, die sich kennen (also über eine gemeinsame Shared-Assembly verfügen) können über die API miteinander kommunizieren.

edit 19.12.2010: Modularitiy habe ich in Version 1.0 wieder rausgenommen. Das ist ein eigenes großes Thema und hat nichts direkt mir Kommunikation zu tun. Ich werde das Thema in einem anderen Open Source Projekt adressieren.

Das ist alles natürlich noch sehr ausbaufähig.
boonkerz
Kompiliert das auch gegen Mono?
Rainbird
Hallo boonkerz,

ich habe Zyan eben mit dem Mono Migration Analyzer (MoMa) analysieren lassen. Du findest das den MoMa-Prüfbericht unten im Anhang als PDF.

Es sind nur ein paar Kleinigkeiten.

Die CustomErrors-Eigenschaft ist in Mono wohl(noch) nicht implementiert. Die braucht man aber nicht zwingen, damit Zyan läuft. Über CustomErrors wird eingestellt, ob Exceptions vom Server serialisiert und zum Client übertragen werden sollen, oder nicht.

Dann wird an zwei Stellen ein Typvergleich gemacht, der nicht ganz mono konform ist. Sollte auch kein Problem sein, das anzupassen.

Zu guter letzt hat MoMa noch zwei P/Invokes gefunden. Die werden beide vom Zyan.Communication.Security.BasicWindowsAuthProvider abgesetzt. Dieser Authentifizierungsprovider ist optional und speziell für die Prüdung von Windows-Benutzern entwickelt. Da ich diese P/Invokes nicht sinnvoll ersetzen kann, wird der BasicWindowsAuthProvider unter mono nicht funktionieren. Vermutlich würde ihn aber auch kein mono-Entwickler vermissen, da er vom Zweck her schon Windows bezogen ist.

Es sind also keine unlösbaren Probleme. Ich werde den Zyan-Code entsprechend anpassen und einen Test mit mono machen.

Ich versuche es so hinzukriegen, dass MS.NET und mono mit der selben Assembly arbeiten können. Das sollte doch wie folgt funktionen, oder?

C#-Code:
public static class MonoCheck
{
    public static bool IsRunningOnMono()
    {
        return Type.GetType ("Mono.Runtime") != null;
    }
}

...

if (MonoCheck.IsRunningOnMono())
    Console.WriteLine("Mono Implementierung");
else
    Console.WriteLine("Microsoft.NET Implementierung");

Neuigkeiten zur mono-Unterstützung von Zyan, werde ich hier posten.
Rainbird
Hallo boonkerz,

ich habe die kleinen Problemchen im Code behoben und die Änderungen bei Codeplex eingecheckt. Hier kannst Du die erste mono-taugliche Version abrufen:  http://zyan.codeplex.com/SourceControl/c...et/changes/4988

Den mono-Test habe ich mit mono 2.8 unter Windows durchgeführt. Ein Test unter Linux steht noch aus (Das aktuelle VMWare Image wird gerade heruntergeladen und ist leider erst in ein paar Stunden fertig Augenzwinkern )

Aber unter Windows schnurrt Zyan schon auf der mono Laufzeitumgebung, was folgender Screenshot zeigt:
boonkerz
Hallo,

Ich hatte bei meinem Projekt damals auch WCF eingesetzt.
Allerdings war das schon extrem aufwendig.

 http://www.thomas-peterson.de/tpwawi/screenshots.html

Nun ist die Frage ob ich das evtl mit deiner Lösung einfacher geht.
Und da ich inzwischen auf Mac OS unterwegs bin :)
Rainbird
Hallo boonkerz,

Zyan verwendet unter der Haube .NET Remoting. Der Vorteil von .NET Remoting ist, dass man Objektreferenzen übertragen kann und nicht - wei bei WCF - zwangsweise der Serviceorientiertheit verhaftet ist.

mono hat eine sehr gute Unterstützung für .NET Remoting. Deshalb konnte ich Zyan auch in wenigen Minuten unter mono zum laufen bringen. WCF ist nur teilweise in mono implementiert. Aber selbst wenn es zu 100% implementiert wäre, ist WCF generell kompliziert und sehr aufwändig (wenn man nicht nur Standard-0-8-15 machen will).

Wenn meine mono Tests unter Linux (MacOS steht mir leider nicht zur Verfügung) erfolgreich sind (was spätestens nach ein paar kleinen Korrekturen so sein wird), kann man Zyan auch für plattformübergreifende Kommunikation einsetzen.

Was die Einfachheit angeht, sollte Zyan WCF definitiv etwas vorraus haben, da einfache praktische Anwendung mein wichtigstes Entwurfsziel war (bzw. ist, da Zyan ja noch nicht ganz fertig ist).

Es würde mich freuen, wenn Du Dir die Zeit nehmen würdest, um Zyan auf MacOS einfach mal auszuprobieren. Wenn es irgendwelche Fehler gibt, lassen die sich bestimmt ohne großen Aufstand beheben.
boonkerz
Hallo,

Wenn ich mir die Demo so anschaue hätte mir das viel Arbeit gespart.
Im Grunde habe ich ja wcf nur zur übertragung benutzt.
Da war schon extrem viel Overhead dabei.

Ich schau mal ob ich das zum laufen bekomme.
Die Solutions bekomme ich auf allerdings sind die assymblys ja nicht da :)
Rainbird
Hallo boonkerz,

ich habe eben erfolgreich einen String zwischen zwei mono Prozessen auf Linux mit Zyan versendet. Den aktualisierten Zyan-Code findest Du in folgendem Changeset:  http://zyan.codeplex.com/SourceControl/c...et/changes/5062
Rainbird
Hallo boonkerz,

im Anhang findest Du die Test-Solution meines kleinen Linux-Tests inklusive Binaries.
Starte einfach ZyanTest.Server.exe und dann ZyanTest.Client.exe.

Es ist nur eine kleine Echo-Implementierung. Du kannst im Client einen Text eingeben, der dann zum Server versendet wird. Der Server sendet die Antwort wieder 1:1 zum Client zurück.

Wäre super, wenn das auf dem Mac gleich auf Anhieb laufen würde.

Folgendes ist mir beim entwicklen mit monoDevelop aufgefallen, was zu beachten ist:
  • Zielframework muss von 3.5 auf 4.0 umgestellt werden
  • Verweis auf System.Core muss manuell zugefügt werden
Wenn Du es zum laufen bringst, kannst Du dann bitte einen Screenshot hier posten?
boonkerz
Läuft soweit :)

Danke
Rainbird
Hallo zusammen,

die Testphase ist vorbei. Zyan 1.0 steht zum download bereit:  http://zyan.codeplex.com/releases/view/57797.

Wichtigste Neuerung sind die gesenkten Systemanforderungen. Sowohl Client- als auch Serverseitig kommt Zyan jetzt mit .NET 3.5 Client Profile aus.
luciluke
Hallo rainbird,

ich versuche gerade eine kleine Anwendung auf Zyan umzustellen, da mir Zyan doch sehr gut gefällt.
Nun bin ich auf folgendes Problem gestoßen.
Es gibt bei mir Methoden, die nicht zwingend alle Parameter brauchen, sodass es auch vorkommt, dass ein Parameter mit NULL übergeben wird.
zB.:
Console.WriteLine(proxyA.GetHelloMessage("a",null));

Dies führt aber nun zu einem Fehler bei

C#-Code:
            // Alle Parameter durchlaufen
            for (int i = 0; i < args.Length; i++)
            {
                // Typ in Array einfügen
                types[i] = args[i].GetType();
            }

in Zyan ComponentInvoker.cs

Meine Frage wäre, ob dass so von Dir beabsichtigt nicht möglich ist Null zu übergeben, oder ob es Sinn macht da noch etwas zu ändern.

ps.: Allen ein gutes, glückliches, gesundes und auch erfolgreiches neues Jahr 2011