Heute noch mal wieder zu dem letzten Teil der K&D-Vorlesung begrüßen.
Bei dem, wie gestern schon versucht zu motivieren, Middleware ist
eigentlich die Komponente, die im verteilten System sozusagen das
Geschehen beieinander hält und in dem Sinne eben auch Datenübertragung
zusammen integriert.
Das heißt, diese Zusammenführung ist eben genau die wichtige Aufgabe
von der Middleware.
Und ich werde jetzt versuchen, heute und nächsten Donnerstag eine Art
Tieflug durch Middleware zu machen.
Kann man natürlich in zwei Vorlesungsstunden nicht im Detail machen,
aber Sie sollen mitnehmen, ein Gefühl, was könnte es sein.
Welche Ziele haben wir?
Das sind Ziele, die einfach gestern auch schon genannt waren.
Skalierbarkeit ist immer etwas, was wir im Auge haben müssen.
Das gilt für Datenverwaltungssysteme, wie Sie ja beim Herrn Lockermann
eindringlichst auch mitbekommen haben.
Aber das gilt immer auch, wenn Sie Datenübertragung machen.
Also Sie müssen sich überlegen, für wen entwickeln Sie das System, wie
viele Benutzer wollen Sie da tatsächlich dran lassen.
Das heißt, bis zu welcher Größenordnung skaliert so etwas.
Sprich, sinkt die Leistungsfähigkeit nicht unnötig ein.
Offenheit, das ist wieder so ein schöner Punkt, der da steht, der
relativ global ist.
Was ist Offenheit?
Sollte Ihnen in der Datenübertragungssparte schon klar geworden sein,
Sie brauchen irgendwo Standardansätze, mit denen Sie arbeiten können.
Das heißt, Systeme, die spezifiziert sind, die offengelegt sind und
die Sie benutzen können.
Das ist ein wichtiger Faktor, den man am Anfang gelegentlich vergessen
hat.
Besonders im Datenkommunikationsbereich.
Da haben Sie sich am Anfang hingesetzt und haben irgendwelche Lösungen
gemacht, proprietäre Lösungen einzelner Firmen, die Sie nicht
offengelegt haben und die zum Teil schlicht und einfach wieder in der
Versenkung verschwunden sind.
Heute haben Sie in dem Bereich offene Standards.
Sie haben die TCP-IP-Welt, die verwendet wird.
Das heißt, auch hier in der Mittelwelle wird man sich überlegen
müssen, wenn ich sowas mache und eigentlich die große, weite Welt
sozusagen damit zusammenkitten will, wie offen will ich denn sein?
Und klar gibt es immer irgendwo so zwei Lösungen, die man fahren kann,
die man bei Systemen häufig sieht.
Entweder man versucht, viele in ein Boot zu kriegen und gemeinsame
Lösungen zu erarbeiten oder man heißt Microsoft und macht es allein
und hofft, dass die Welt es übernimmt.
Bei Ihrem neuen Versuch .NET ist man sich da noch gar nicht so sicher,
ob der wirklich breiten Anklang findet.
Das ist immer der schmale Grad, auf dem Sie laufen.
Im Kommunikationsbereich haben es die Firmen früher versucht.
Da gab es IBM-Kommunikationssysteme, da gab es DEC
-Kommunikationssysteme.
Heute ist alles Standard.
Die haben sich alle nicht wirklich durchgesetzt.
Also das ist eine Sache, die man sich überlegen wird.
Das große Ziel ist, dass Sie Dienste koppeln wollen.
Das heißt, Sie haben Dienste, die irgendwo im System verfügbar sind.
Nicht unbedingt physikalisch, sondern auf der gleichen Maschine.
Und die wollen Sie miteinander verbinden, um nachher verteilte
Anwendungen bereitstellen zu können.
Ich sage gerne mal Lachs, naja Mittelmeer macht den Unterschied aus.
Das heißt, eine gute Mittelmeer und Sie kriegen ein gutes
Gesamtsystem.
Und ich finde so das Beispiel Sandwich macht das nochmal ein bisschen
anschaulich klar.
Ohne das in der Mitte ist die Sache ziemlich trocken und nicht so
wirklich schick.
Aber die Fragen, die dann von Interesse sind, ja, hm, was mache ich
denn jetzt dazwischen?
Das heißt, was tue ich wirklich in meine Mittelmeer rein?
Das ist natürlich auch die Spannende.
Weil wenn Sie es falsch herein tun, ist das System vielleicht nicht
tauglich.
Oder bei dem Beispiel, Ihr Sandwich schmeckt Ihnen nicht.
Was ich jetzt erstmal machen möchte, ist, das ganze Kapitel hier
versuche durchzuhalten, ist zunächst mal die Konzepte klar zu machen,
um welche Fragestellungen geht es.
Und dann jeweils ein Beispiel ranziehen, einer Mittelmeer, uns dort
ein bisschen konkretisieren.
Und das heißt, bevor wir aber da reingehen, müssen wir uns erstmal
überlegen, was gehört denn jetzt zu den Aufgaben.
Gestern habe ich viel davon erzählt, das sitzt da irgendwo in der
Mitte, ist der Glue, ja, soll alles irgendwie homogen machen, also
eine virtuelle Homogenität, die da oben drüber gelegt wird.
Das ist schon mal eine Sache, die eben ganz wichtig ist und die wir
uns im Detail anschauen werden.
Wo sind denn da jetzt Punkte der Heterogenität, die uns stören und die
wir überwinden müssen?
Und was kann die Mittelmeer dazu beitragen?
Es gibt zunächst zwei Kategorien, die Sie unterscheiden können.
Das ist einmal die technische Interoperabilität und zum anderen die
semantische.
Wir werden uns im Rahmen der Vorlesung hier auf die technische
Interoperabilität stürzen und schauen, was gibt es dort für Probleme
und wie werden wir damit umgehen können.
Dann haben wir verteilte Systeme.
Das heißt, irgendwie wird die Mittelmeer damit umgehen müssen, dass
die Verteilung vorhanden ist und dass sie eigentlich für den Anwender
obendran möglichst transparent sein sollte.
Das heißt, im Prinzip sollten Sie nachher Software entwickeln können,
Anwendungssoftware, die in einem verteilten System läuft, aber Sie
sollten nur möglichst wenig von dem verteilten System wissen müssen.
Das heißt, unabhängig davon das System entwickeln können.
Und ich sage ganz bewusst möglichst wenig.
Nämlich, dass Sie gar nichts davon wissen, dass das eventuell verteilt
läuft.
Das wird man nicht hinkriegen.
Bei der Verteilung spielt einmal natürlich der Aspekt, dass Sie einen
anderen Adressraum haben, eine wichtige Rolle.
Das heißt, Sie können nicht davon ausgehen, dass Sie wissen, wo Dinge
im Speicher liegen.
Zum anderen spielt die räumliche Distanz eine Rolle.
Das klingt jetzt total primitiv, aber Ihre Daten müssen von hier nach
hier.
Und das geht in der Regel langsamer in einer Maschine irgendwie zu
adressieren.
Und das ist auch einer der Gründe, oder beides, der Adressraum und die
räumliche Distanz sind Gründe dafür, dass es Ihnen nicht gelingen
wird, eine komplette Homogenität und Transparenz oben hinzulegen.
Sie immer damit leben müssen, dass es möglicherweise länger dauert und
dass es möglicherweise in einem anderen Adressraum stattfindet.
Was man versucht, ist es möglichst transparent zu machen.
Und das werden wir gleich sehen, wie.
Dann ist die Sache, gestern nochmal das Fluggastbeispiel, mit vielen
Datenverwaltungen, die in Anspruch genommen wurden.
Wie finden Sie eigentlich die Dinger?
Woher wissen Sie, welchen Dienst Sie wohl in Anspruch nehmen, auf
welcher Maschine?
Irgendjemand muss das entscheiden und irgendjemand muss über das
nötige Wissen darüber verfügen.
Und auch das ist eine der ganz wichtigen Aufgaben, die die Middleware
hat.
Ihren Dienstgeber eben zu finden, die Dienstgeber bekannt zu machen
und damit die Zuordnung Dienstnehmer, Dienstgeber zu realisieren.
Diese drei Aufgaben werden wir uns näher angucken.
Die jeweils einigermaßen detaillierten Beispielen.
Dann gibt es eine ganze Reihe anderer Dinge, die wichtig sind, die wir
aber nicht in dem Detaillierungsgrade hier zumindest uns jetzt
anschauen können.
Beispielsweise Dienstaktivierung und Beendung.
Wenn Sie einen Dienst anbieten, bieten Sie den möglicherweise nicht
rund um die Uhr an.
Oder möglicherweise muss er gewartet werden und er steht nicht zur
Verfügung.
Wie machen Sie das?
Das müssen Sie bekannt geben.
Muss irgendwie Hand in Hand auch gehen hier mit der Vermittlung der
Dienstgeber?
Wie gehen Sie also mit dieser Dynamik nochmal um?
Und dann kommen so natürliche Sachen ins Spiel, wenn sie verteilt
sind.
Sie haben möglicherweise mehrere Orte, an denen meinetwegen die
Flugdaten und solche Geschichten gespeichert sind.
An welchen machen Sie es denn?
Wie verteilen Sie die Last auf das System?
Das ist eine Aufgabe, die ebenfalls in der Middleware zu lösen ist.
Das heißt, sie muss sich mit dem Scheduling, Lastverteilung und
solchen Geschichten befassen.
Sicherheit?
Tja, wenn ich irgendwo ein E-Business mache und meine Kreditkarte
angebe und dann Geld abgebucht wird und solche Geschichten, habe ich
ein Bedürfnis nach Sicherheit.
Das sollte möglichst auch eben von der Middleware unterstützt werden.
Auch das ist ein Bereich, der wichtig ist, den wir leider nicht
abdecken können hier.
Persistenz?
Da werde ich nochmal kurz später drauf eingehen.
Wenn Sie zustandsbehaftete Dienste haben, die müssen Sie persistent
bereitstellen.
Auch das muss mit der Middleware funktionieren.
Wie tut sie das?
Und die Unterstützung von Transaktionen ist genauso ein wichtiges
Gebiet.
Die beiden hier, wenn Sie sich das anschauen, schon wieder relativ nah
von den Diensten an der Datenverwaltung einfach dran.
Damit sehen Sie, die Middleware hat im Prinzip in beide Richtungen,
Datenübertragung, Datenverwaltung, auch Füßchen, wo sie reingeht.
Die oberen hier sind sicher eher von der Datenübertragung zu sehen.
Hier unten haben wir ganz direkt die Glue sozusagen zur
Datenverwaltung hin wieder.
Wie macht man es jetzt prinzipiell?
Gibt es unterschiedliche Möglichkeiten das zu tun?
Vielleicht gehen wir erstmal auf die Folie hier.
Im Prinzip haben wir jetzt relativ abstrakt von Anforderungen
gesprochen.
Wie kann ich es tun?
Und wie kann ich Middleware, die heute existiert, auch klassifizieren?
Es gibt einmal die Unterscheidung RPC vs.
Asynchroner-Systeme.
RPC steht dabei für Remote Procedure Call.
Man kann meine Schrift normal schon nicht gut lesen.
Dadurch wird es glaube ich nicht besser.
Man kann es grob raten.
Was ist der Unterschied?
RPC ist im Prinzip ein programmiersprachlicher Aufruf einer entfernten
Funktion und typischerweise blockiert es.
Das heißt sie sind irgendwo in ihrer Middleware eingetaucht, rufen
eine Funktion auf einem anderen System auf und warten hier erstmal.
Bis das sich zurückmeldet und die Antwort zurückkommt.
Sie sind also synchron und gehen nicht in ihrem Kontrollfluss weiter.
Typischerweise ist das das Modell was irgendwelchen prozedur- oder
objektorientierten Systemen zugrunde legt.
Eine ganz andere Sache ist die Asynchroner-Kommunikation-Messaging
-Systeme, in denen sie typischerweise Dateien oder sowas verlagern,
also einfach irgendwie eine Datei wegschicken, aber als Wegsendende
dann nicht auf eine Rückantwort warten.
Das heißt hier eher Daten, Dokumente und sowas im Vordergrund.
Das heißt man wird sich wohl aussuchen müssen, wenn man das so sieht,
je nach Einsatz, was ich für eine Middleware mache, würde
dementsprechend widersprechen, was ich vorhin gesagt habe, dass man ja
eigentlich die Eier legende Wollmilchsau dazwischen finden möchte.
Was sie heute finden, sind durchaus beide Varianten innerhalb einer
Middleware, die unterstützt werden.
Die nächste Frage, die man sich stellen kann, es geht ja letztendlich
um Implementierung, Realisierung verteilter Anwendungen.
Mit welcher Sprache mache ich es denn?
Vielleicht würden jetzt einfach die meisten sagen Java, weil sie mit
Java aufgewachsen sind.
Dann würde ich sagen, naja, vielleicht C++, das ist eher was, mit dem
wir noch aufgewachsen sind.
Hm, stellt die grundsätzliche Frage in den Raum, wollen sie das
Sprachabhängig machen oder wollen sie es unabhängig machen?
Und beide Varianten haben wir heute auf dem Markt.
Einmal Corbo hier, was den außerordentlichen Vorteil hat, dass ich
tatsächlich Anwendungen integrieren kann, die in unterschiedlichen
Sprachen geschrieben sind.
Oder Java Enterprise.
Java.
Ob man mit diesen homogenen Systemen wirklich glücklich wird, ist noch
eine Frage.
Sie machen einen nicht bei allen Implementierungsaufgaben wirklich
glücklich, vor allem dann, wenn man Systemen näher implementieren
möchte.
Ja, und dann ist die Sache, die ich eben schon angesprochen hatte,
proprietär versus standardbasiert.
Und eben die Gretchenfrage, ja, was tue ich, bin ich sozusagen Dampfer
genug, um eine eigene Lösung voranzutreiben und damit ein Business zu
machen.
Letztendlich wollen sie Geld verdienen, die Firmen, die das
bereitstellen.
Und eine ganz interessante Frage ist noch, die, die ganz unten hier
aufgelistet ist, mit Embedded versus Enterprise.
Was wir heute typischerweise sehen, sind Enterprise-Lösungen für, was
weiß ich, Finanzdienstleistungsdinge etc.
pp.
Da setzen so wunderschöne Middleware ein.
Die ist mit der Zeit ein bisschen gewachsen, ein bisschen groß
geworden, deswegen hat man die typischerweise bis vor kurzem
eigentlich nur auf normalen Rechnern drauf gehabt.
Es gibt einen zunehmenden Trend, so eine Middleware auch auf kleine
und Kleinstgeräte drauf zu bringen.
Das heißt auch ihr PDA soll eine Middleware haben, aber auch
meinetwegen letztendlich der Prozessor, der irgendwo im Auto drin
sitzt und irgendeine Steuerung macht, sollte auch über eine Middleware
verfügen.
Und das sind Dinge, die heute durchaus aktuelle Entwicklungen sind.
Wie kriege ich den großen Elefanten-Middleware, den man entwickelt
hat, wieder in so eine kleinere Maus, die dann auch wieder in so ein
Embedded -System reinpasst.
Welche Varianten der Middleware werden wir uns anschauen im Rahmen der
Vorlesung?
Das ist einmal Cobra, steht für Common Object Request Broker
Architecture.
Wichtig ist da durchaus das Wörtchen Architecture, da wird also eine
Gesamtarchitektur dahinter definiert.
Und Ziel ist es eben ein verteiltes Rahmenwerk für Softwareentwicklung
damit bereitzustellen.
Das Ding ist in einem Gremium standardisiert worden.
Das heißt, das ist keine Lösung, die jetzt einen in die Runde geworfen
hat.
Hat einen relativ langen Entwicklungszyklus schon durchlaufen und ist
heute aber recht stabil, zumindest in seinen Kernkomponenten.
Mit der Oma, den Opa haben sie irgendwie nicht entwickelt dazu, ist
eine Referenzarchitektur entworfen worden, die wir uns nachher gleich
ein bisschen anschauen werden, wie die aussieht.
Das System werden wir jeweils als Case Study nehmen.
Wenn wir uns eine Aufgabenstellung konzeptionell angeschaut haben,
dann werden wir schauen, wie hat das Cobra gelöst.
Cobra selbst finden sie in einer Reihe Public Domain Implementierungen
mit unterschiedlichen Varianten.
Eine relativ gute Variante, Miko, durchaus auch in Deutschland
entstanden und sie finden sie in verschiedenen Produkten, Orbex und
solchen Geschichten.
Die neue Entwicklung und das neue Schlagwort im Internet heißt heute
Web Services.
Ja, ist sicher eine wichtige Sache.
Man steht heute so ein bisschen, wenn sie die Literatur lesen, auf dem
Standpunkt, wow, Web Services, das Internet ist gerettet,
wahrscheinlich brauchen wir die nächsten 5 Jahre keine Forschung mehr
auf dem Bereich.
Würde ich nicht so definieren.
Was ist der Vorteil davon, den man hat?
Man ist webbasiert.
Das heißt, man baut seine Middleware sozusagen aufs Web obendrauf.
Verwendet dazu dann die Protokolle, die sie teilweise, ja die
Geschichten, die sie bei Herrn Abeck auch schon kennengelernt haben.
Einmal ein Protokoll zur Kommunikation, ein einheitliches.
HTML zur Präsentation und Adressierung URLs.
Das heißt, was man im Prinzip macht, wenn sie sich den Protokollstack
anschauen, da hat man irgendwie dazwischen mal TCP.
Dann kommt HTTP.
So und da obendrauf setzt man die Geschichte jetzt.
Das heißt, sie verwenden den Transport, schon mal transparent, setzen
das über HTTP drauf und machen die Middleware dort.
Was hat das für einen Vorteil?
Der entscheidende Vorteil ist, dass ein ziemlich großer Teil der Welt
heute über HTTP lebt.
Ob das gesund ist oder nicht, würde hier zu weit führen, das zu
diskutieren.
Ja und dann werden wir uns ganz kurz noch nachrichtenorientierte
Middleware angucken.
Die eben darauf hauptsächlich basiert, Daten, also Dokumente oder
sowas zu verschicken.
Die eine asynchrone Kommunikation darstellt, aber trotzdem müssen wir
uns auch dort gewisse Gedanken über Persistenz machen.
Und das werden wir dann am Ende dieses Kapitels uns eben ein bisschen
anschauen.
Web Services wird nächsten Freitag dann drankommen.
Was sind die Herausforderungen?
Das kann man ganz einfach zusammenfassen.
Naja, ich will möglichst flexibel sein, weil ich will viele Dienste
anbieten.
Ich will neue Dienste dazu stöpseln können, alte rausnehmen können und
ich will leistungsfähig sein.
Passt nicht zusammen.
Das sind zwei Eigenschaften, die zusammen nicht wirklich realisierbar
sind.
Die Frage ist jetzt, wie weit gehen sie Richtung Flexibilität und wo
machen sie Schranken, um eine Leistungsfähigkeit noch auf einem
relativ hohen Level garantieren zu können.
Dann habe ich sowas hier nochmal hingeführt wie Hooks für Power User.
Es gibt natürlich Anwender, die gehen her und wollen ihre Middleware
einfach verwenden.
Dann gibt es aber natürlich diejenigen, die wollen die Middleware auch
auf sich zuschneiden.
Die wollen neue Dienste reinmachen, die wollen die Middleware
erweitern.
Sie wollen sie auf ihre spezifischen Bedürfnisse hin konfigurieren
können.
Und dadurch können Sie sich vorstellen, wird das Ganze schon wieder
relativ komplex.
Dann stellt sich auch die Frage, wie lässt sich das wieder mit
Leistungsfähigkeit vereinigen.
Grundsätzlich versucht man das Ganze konfigurierbar zu machen.
Ist eine schöne Eigenschaft, nur muss man aufpassen, wird die
Konfiguration schon wieder so kompliziert, dass es nachher eine
Programmierbarkeit ist, die gefordert wird.
Und das ist dann wichtig, wenn Sie sich überlegen, wer die Dinge
benutzt und was sie tatsächlich vom Benutzer nachher ankennt, müssen,
erfordern.
Ziel haben wir, denke ich, schon ausführlich gesagt.
Wir wollen so die große weite Welt einfach integrieren.
Und das Neueste auf dem Trend ist einfach Web-Services, die wir uns am
Schluss auch anschauen werden.
Jetzt gehen wir auch mal die Punkte durch, die wir als Aufgaben zu
lösen haben.
Und eine der Aufgaben ist schlicht und einfach, wir müssen die
Verteilung überwinden.
Sie haben typischerweise in solchen Systemen eben hier unten einfach
Ihr Internet dazwischen.
Sie haben hier den Dienstnehmer, hier haben Sie den Dienstgeber und
der will hier irgendwie einen Dienst in Anspruch nehmen.
Und das kann eben jetzt einfach eine Prozedur sein, eine Funktion, die
Sie aufrufen sollen.
Das kann ein Objekt sein und so weiter.
Was Sie nicht hinkriegen werden, ist komplett die Distanz hier
unsichtbar zu machen.
Weil schlicht und einfach müssen Sie die überbrücken.
Es sind physikalische Grenzen, über die Sie nicht hinauskommen.
Was jetzt schön wäre, wenn ich eine Anwendung schreibe, dass ich das
relativ unabhängig davon machen könnte, ob jetzt der Dienstgeber hier
drüben sitzt oder hier vielleicht auf der gleichen Maschine.
Das heißt, ich würde eigentlich ganz gerne den Aufenthaltsort des
Dienstgebers transparent machen.
Also eine Ortstransparenz erreichen.
Geht nicht ganz so einfach.
Die Leistung haben wir einmal schon gesagt, ist eine Sache, auf die
man achten muss.
Das bezieht sich auf die Verzögerung dazwischen, physikalische
Laufzeiten.
Das Signal hat nun mal einfach nur 200.000 km pro Sekunde, in der
Regel, die es zurücklegt in den meisten Medien.
Und dann müssen Sie auch nochmal beachten, wie dick ist eigentlich
Ihre Internetanbindung.
Wenn da einer über ISDN dran sitzt mit 64 Kilobit, können Sie sich
vorstellen, steigt die Verzögerung auch durch den geringen Durchsatz.
Parameterübergabe ist so eine Sache, die können Sie auch nicht
komplett transparent machen.
Sie als Java-aufgewachsene Informatiker neigen vielleicht eher dazu.
Die Leute mit C sind dann ein bisschen sensibler, was solche Dinge wie
Zeiger zum Beispiel angeht.
Die zeigen auf dem Adressbereich in Ihrem eigenen Adressraum, da
sollten Sie wissen, was drin steht.
Ja, was machen Sie denn, wenn Sie so einen Zeiger jetzt haben, als
Parameter und hier drüben eine Funktion aufrufen wollen?
Dumm gelaufen?
Keine Zeiger mehr?
Wäre auch dumm.
Das heißt aber, Sie müssen sich was überlegen, wie Sie sowas mit
Kopieren etc.
pp.
lösen können.
Das heißt, da ist schon mal keine 100% Transparenz möglich.
Naja, und Fehlermodell, das ist natürlich auch so eine Sache.
Dann müsste Sie der Herr Abick relativ stark doch dafür sensibilisiert
haben, dass in dem Bereich hier, innen drin im Netz, jede Menge an
Fehlern auftreten können.
Ihre Verbindung kann abbrechen, wenn Sie drahtlos sind und zum
Beispiel um die Ecke gehen, plötzlich keine Funkanbindung mehr haben,
ist die Verbindung weg.
Sie können Fehler haben.
Ihr Router im Netz, der kann sagen, ich habe jetzt keine Lust mehr,
ich bin überlastet.
Alles was kommt, schmeiße ich gleich wieder weg.
Das wird wohl Auswirkungen auf die Anwendungsebene oben haben.
Das heißt, auch hier muss man das mit berücksichtigen, das ist eine
andere Geschichte, als ob Sie im gleichen Adressraum auf der gleichen
Maschine sitzen.
Da haben Sie diese Fehler nicht, müssen mit denen nicht umgehen.
Das heißt aber, im Prinzip wollen wir erreichen mit der Mittelwehr,
möglichst ortstransparent zu sein.
Trotzdem sollte der Programmierer sich potenziell im Klaren darüber
sein, da ist eine Verteilung drin.
Und da können Dinge passieren und Verzögerungen entstehen, mit denen
ich sonst nicht gerechnet habe.
Wie ist das grundlegende Paradigma?
Es kam in der Vorlesung schon ein paar mal zur Sprache, kleinen
Server, Dienstnehmer, Dienstgeber-Verhältnis.
Das heißt, Sie haben hier eben jemanden, der die Dienste zur Verfügung
stellt.
Und Sie haben den Client, der hier per Anfrage die Dienste in Anspruch
nehmen will.
Das ist erstmal die ganze Basissituation.
Die haben Sie übrigens sogar in Ihrem TCP-Protokoll drin.
Das hat Herr Abe, glaube ich, nicht in dem Detail gemacht, aber im
Prinzip haben Sie hier TCP auf dem Server, warten, wenn das ein Web
-Server ist, und der Client macht einen Verbindungsaufbau dahin.
Das war die Sache gestern mit, wenn das der Client-TCP ist, mit dem
Synchronisation -Paket, macht der eine Verbindung darüber.
Der Server, die TCP-Instanz, sitzt hier, wartet auf den, hört auf den
berühmten Port 80 und baut dann eine Verbindung auf.
Das heißt, schon so weit unten im Datenübertragungssystem haben Sie
Client -Server-Beziehungen.
Die sind relativ inhärent im ganzen Kommunikationsgeschehen mit dabei.
Client-Server-Rollen sind unterschiedlich, das ist ein asymmetrisches
Verhältnis, was sich gerade beim Web auch in einem hochgradig
asymmetrischen Verkehrsaufkommen widerspiegelt.
Sie haben kurze Anfragen, Sie kriegen sehr viele Daten zurück,
gegebenenfalls.
Die Rollen können sich ändern, das heißt, so ein Server kann auch eine
Client -Rolle annehmen, wenn er dann die Anfrage, die hier kam, an
einen anderen Server weiterleitet, um sie dort bearbeiten zu lassen.
Das ist, glaube ich, noch nicht so furchtbar neu.
Das lag aber der ganzen Geschichte sozusagen zugrunde.
Dann hat man genau dieses RPC, was ich vorhin schon erwähnt hatte, den
Remote Procedure Call entwickelt.
Das war eine Geschichte Anfang der 80er Jahre.
Damals eine unheimlich wichtige und sozusagen revolutionierende
Entwicklung, weil zu dem Zeitpunkt war man an einem Stand angelangt,
wo gerade mal so Ethernet-Tokenringe, also lokale Netze, das Laufen
gelernt haben.
Da kamen wirklich in den großen Einsatz überhaupt mal die ersten PCs
rein.
Und schon in dem Augenblick gab es Leute, und das sind vor allem
Nelson Burel aus den USA, die dafür verantwortlich waren, die eben
sich überlegt haben, wie mache ich da vernünftige Implementierungen
verteilt möglich.
Die Idee dahinter war jetzt einfach, ich will weg von den
Kommunikationsprotokollen, also von irgendwie TCP-Syn oder sonst was,
da will der Anwender ja nichts mit zu tun haben eigentlich.
Der will nur, dass das funktioniert.
Der Anwender denkt in seiner Programmiersprache.
Also war die revolutionäre Idee zu dem Zeitpunkt, lasst uns einen
programmiersprachlichen Ansatz machen, sodass der Entwickler
weiterarbeiten kann, wie er es gewohnt ist.
Datenaustausch, sollte er sich bewusst sein, da passiert irgendwas da
unten drin, aber der soll überhaupt nicht verstehen, wie es
funktioniert.
Dem soll nur klar sein, da können Verzögerungen reinkommen.
Fehlermodelle muss man ein bisschen betrachten.
Das Ganze lokalisiert überhaupt von UDP-TCP.
Das war zum damaligen Zeitpunkt eine durchaus weise Entscheidung.
Sie würden jetzt sagen, klar macht man das über UDP und TCP.
Gibt ja sonst nichts.
Zum damaligen Zeitpunkt hat die Welt noch im ISO-OSI-Referenzmodell
gekämpft und ISO-OSI-Standards und Protokolle versucht zu realisieren
und implementieren.
Und gegen TCP und UDP anzukämpfen.
Also damals war das durchaus nicht unbedingt naheliegend, es war eine
gute Idee, dass sie es darüber gemacht haben.
Und die Idee dahinter war, das Ganze synchron zu machen.
Das heißt, Sie haben hier den Dienstnehmer, der hat seinen
Kontrollfluss hier, also irgendein Programm, das arbeitet.
Und das Programm wird hier jetzt zunächst mal unterbrochen, macht
einen Prozeduraufruf, der eben jetzt hier rüber geht, an die andere
Maschine.
Dort erfolgt die Bearbeitung von dem Teil, das Ganze geht zurück und
hier darf der jetzt wieder lokal weiterarbeiten.
Das kann man natürlich dann beliebig in verschiedene Richtungen
nacheinander ausführen.
Und damit habe ich jetzt die Möglichkeit, egal wo die Prozedur läuft,
ich kann sie aufrufen, kann somit verteilt arbeiten.
Das heißt, ich habe einmal Ortstransparenz realisiert, weil es im
Prinzip für mich egal ist, wo das Teil abläuft.
Ich bin plattformunabhängig, zumindest soweit, was die Systeme hier
angeht, die unten drunter liegen und das Betriebssystem.
Und ja, ich brauche mich um diese Programmierschnittstelle hier nicht
mehr zu kümmern.
Das berühmte Socket API, was fast jeden, der es zum ersten Mal
benutzt, erst mal zur Verzweiflung bringen lässt.
Darum braucht sich jemand, der hier Anwendungen realisiert.
Der also hier arbeitet, nicht mehr zu kümmern.
Der macht hier einen ganz einfachen Prozeduraufruf.
So wie es gewohnt ist.
Der Rest passiert magisch unten drunter.
So, was gehört jetzt alles dazu, um sowas tatsächlich realisieren zu
können?
Der Dienstnehmer und der Dienstgeber sind einmal die Funktionen hier,
der Funktionsaufruf.
Dann beim Dienstgeber die Sache, ich gehe jetzt tatsächlich in die
Funktion rein, arbeite die ab.
Dann haben wir hier das Senden, was wir eben gesehen haben, also der
RPC -Request, der hier rausgeht, der drüben empfangen wird und hier
die Kommunikation zurück.
Und dann haben wir noch einen Teil, der neu ist.
Das ist sozusagen der neue Teil dazwischen.
Die beiden Teile.
Nämlich ein Stub und ein Skeleton.
Was machen die jetzt?
Die müssen ja einmal dem Dienstaufruf entgegennehmen.
Die müssen sich jetzt darum kümmern, was ich vorhin schon angesprochen
hatte.
Ja, wir haben Parameter.
Prozeduraufruf mit Parametern.
Okay.
Die muss ich jetzt irgendwie nach drüben transportieren und dazu werde
ich sie geeignet verpacken.
Wie, werden wir uns noch anschauen.
Da muss ich zum Beispiel jetzt berücksichtigen, was mache ich mit dem
Zeiger.
Das unmittelbare Problem, was dort auftauchte, weil das war die Zeit,
wo die Welt ein C programmiert hat und C hat schöne Zeiger dazwischen,
da kann man viel machen.
Das heißt, man musste sich überlegen, wie geht man mit denen um und
wie stellt man sie für die Übertragung dar.
Das als Aufgabe nennt man Marshalling.
Das heißt, man bringt die Parameter sozusagen in eine Kodierung, die
der Gegenpart auch kennt.
Dann geht das Ganze hier rüber.
Auf der anderen Seite muss ich das wieder auspacken.
Wird als Demarshalling bezeichnet.
Dann wird der Funktionsaufruf durchgeführt mit den Parametern, so wie
ich sie lokal auf der Maschine brauche.
Das Ergebnis wird wiederverpackt, also geeignet für die Übertragung
kodiert und dann an den Dienstnehmer weitergeleitet.
Jetzt können Sie sich das Ding anschauen und sagen, na das ist ja ein
schöner Mist.
Jetzt haben wir zwar unsere Funktionen, hier auf den beiden Seiten,
aber jetzt müssen sich die blöden Stubs und Skeletons dazwischen, die
müssen ja irgendwo herkommen.
Das sind Dinge, die werden automatisch generiert.
Und zwar aus der Dienstbeschreibung.
Das heißt aber, aufgepasst, hierzu brauche ich jetzt eine
Dienstbeschreibung.
Die muss ich also schon erzeugen und das erfolgt mittels
standardisierter Sprachen, die wir uns nächste Woche anschauen werden.
Das ist eigentlich einfach nochmal der Prozeduraufruf beschrieben.
Was passiert beim Verpacken alles?
Sie müssen die Daten kodieren und Sie müssen sich im Prinzip erstmal
im Breitstrom organisieren.
Das heißt, jegliche Strukturen und Sachen, die Sie aufbauen, müssen
Sie in Breitstrom umwandeln, um sie dann Byte für Byte übertragen zu
können.
Und die Frage ist, wie tut man das und wie macht man das einigermaßen
effizient?
Der Herr Abbeck hat irgendwann ganz am Anfang der Vorlesung mal über
Bits auf der Leitung gesprochen, wie man eine 0 und eine 1 darstellt.
Im Prinzip ist es das gleiche, nur ein paar Schichten höher.
Sie müssen sich überlegen, wie stellen Sie jetzt ein Array dar, wenn
Sie es übertragen?
Vielleicht noch ein mehrdimensionales.
Wie stellen Sie einfach ein Integer dar, den Sie übertragen?
Weil die andere Seite muss herauskriegen, dass es ein Integer war und
den dann auch richtig kodieren.
Es gibt im Prinzip zwei unterschiedliche Verfahren.
Einmal implizite Kodierung.
Das heißt, Sie wissen einfach aus der Stelle des Parameters bei der
Übertragung, was der für ein Typ ist.
Sie brauchen den Typ nicht bei der Übertragung selbst mitzusenden.
Oder self-identifying.
Das heißt, Sie schicken bei der Übertragung erstmal eine Beschreibung
mit.
Da hinten kommt jetzt ein Integer und dann schicken Sie den Integer
hinten dran.
Und dann kommt jetzt ein Array und dann schicken Sie das Array hinten
dran.
Das brauchen Sie immer dann, wenn Sie dynamische Strukturen haben.
Typischerweise ist man lange Zeit hergegangen und hat gesagt, implizit
ist die Lösung.
Weil da braucht man ja weniger Bits und Bytes zu übertragen.
Davon ist man heute weg.
Weil eigentlich haben wir Kapazität ohne Ende unten im Netz.
Das heißt, wir können auch mehr übertragen.
Mit xml und den Entwicklungen sind wir völlig davon weg, mit solchen
Geschichten einzelne Bits und Bytes einzusparen und die Geschichten
damit unleserlich und unhandhabbar zu machen.
Zeigerparameter hatte ich angesprochen.
Ist klar, verbieten wollen wir sie nicht, denke ich.
Das heißt, Sie müssen irgendwie Copy und Restore machen, um das Ganze
zu übertragen.
Das geht bei einfachen Zeigern noch mit vertretbarem Aufwand.
Wenn Sie richtig komplexe Strukturen haben, wird sowas natürlich
relativ aufwendig.
Und wenn wir jetzt davon gesprochen haben, dass Ihnen die Verteiltheit
nicht komplett transparent gemacht werden wird, dann tragen auch
solche Sachen wie Marschalling die Marschalling dazu bei.
Denn das ist wieder eine Verarbeitung, die mit eingeschoben wird und
die schlicht und einfach Zeit kostet.
Fehlersemantik.
Da muss man sich ein bisschen drüber Gedanken machen.
Weil Sie sind jetzt irgendwie auf Anwendungsebene.
Also es geht nicht mehr um ein einzelnes TCP-Segment, was Ihnen
irgendwo verloren geht, sondern Sie sind auf Anwendungsebene.
Das heißt, Ihnen können entweder anfragen, verloren gehen oder
antworten.
Beides ist nicht besonders günstig.
Stellen Sie sich vor, Sie schicken eine Abbuchung für Ihr Bankkonto
Das bucht ab, die Antwort wird von dem weggeschickt und der IP-Router
unterwegs sagt, interessiert mich nicht, ich habe zu viel Last.
Und Sie schicken nochmal die gleiche Anforderung rüber und dann wird
es bearbeitet.
Und dann wundern Sie sich, dass es zweimal abgebucht ist.
Das heißt, Sie müssen sich da einfach im Klaren sein, welche Fehler
-Semantik steckt hinter dem System, was ich benutze und was hat das
für Auswirkungen auf meine Anwendung.
Weil ich denke, Sie sind nicht glücklich, wenn zweimal das Konto
strapaziert wird.
Es gibt im Prinzip vier verschiedene, die unterschieden werden.
Maybe, ja gut, das ist die traditionelle Sache aus dem Best-Effort
-Internet -Dienst.
Das heißt, kann abgearbeitet werden, kann nicht.
Abgearbeitet werden ist mir völlig egal, ich wiederhole es auch nicht
mehr.
Es wird auch kein zweites Mal ausgeführt.
Und falls ich es doch nochmal wiederhole, dann kann es einfach zu
Duplikaten kommen.
Das heißt, das ist der stupideste Dienst, der, ich glaube, das ist
eindeutig klar, nicht für jede Anwendung wirklich vernünftig
funktioniert.
Dann gibt es die Entscheidung, at least once, at most once und exactly
once.
Exactly once ist klar, da wird genau einmal ausgeführt.
Klar wiederholen Sie es, weil wenn es die Anfrage verloren gegangen
ist, müssen Sie das Ding nochmal rüber schicken und klar filtern Sie
hier auch Duplikate raus.
At least once, das ist jetzt die Geschichte, die natürlich bei
Bankanwendungen nicht so geschickt ist, weil das heißt, es wird
mindestens einmal ausgeführt.
Ob das nachher dreimal ausgeführt wird oder fünfmal, haben Sie nicht
mehr unter Kontrolle.
Auch nicht unbedingt das, was man gemeinhin haben will.
Typischerweise findet man Systeme mit at most once Semantik.
Das heißt, die machen es entweder einmal oder gar nicht.
Wie sieht es mit der Leistungsfähigkeit aus von dem System?
Das habe ich schon gelegentlich erwähnt.
Durchsatz ist klar in Abhängigkeit Ihrer Netzdicke sozusagen.
Geht es eben schnell oder langsam?
Das merken Sie mindestens dann, wenn Sie daheim hinter dem Modem
sitzen und übers Web irgendwelche dicken Daten ziehen.
Die Latenz ist wichtig, die noch mit reinkommt.
Und da spielen mehrere Sachen jetzt eine Rolle, die Sie bei Herrn
Aböck schon gehabt haben.
Zum einen, wenn Sie TCP drunter sitzen haben, bringt Ihnen das ja den
Vorteil, Sie haben einen zuverlässigen Dienst.
Also wird die Realisierung von at most once Semantik oben einfacher
sein.
Das Problem ist, Sie bauen eine Verbindung auf mit einem 3-Wege
-Handshake, so wie das hier dargestellt ist.
Dann schicken Sie Ihre Daten und dann bauen Sie eine Verbindung wieder
ab.
Das heißt, Sie haben, wenn Sie relativ wenig Daten zu schicken haben,
einen ziemlichen Overhead allein durch das Hin und Her vom
Verbindungsaufbau.
Stellen Sie sich vor, Ihre Funktion sitzt irgendwo in Nordamerika
drüben.
Dann kann das relativ lange dauern.
Deswegen wird man typischerweise von den Wire-Protocols, also den
Protokollen auf RPC und Middleware-Ebene, versuchen, eine TCP
-Verbindung mehrfach zu benutzen.
Das heißt, möglichst viele Middleware-Aufrufe über eine TCP
-Verbindung.
Was hat das denn für einen weiteren Vorteil, außer der Tatsache, dass
ich Verbindungsauf- und Abbau spare?
Das hier ist ja erstmal einleuchtend.
Wenn ich eine Verbindung nicht immer aufbauen muss, spare ich mir die
Verzögerung.
Das hat noch einen ganz entscheidenden, anderen Grund, der wichtig
ist.
Was hat denn Herr Abeck alles zu TCP gemacht?
So ganz im Detail ist es ja gar nicht angesprochen worden, aber ein
paar unschöne Eigenschaften davon sind schon gekommen.
Slow-Start ist das Stichwort.
Können Sie noch ein bisschen erläutern, was es war?
Ja, im Prinzip meinen Sie das Richtige.
Das heißt, die Leistungsfähigkeit von TCP sinkt.
Und das passiert genau dann, wenn Sie irgendwie einen Stau im Netz
haben.
Jetzt könnte man sich erst mal fragen, was hat das jetzt mit der
Situation genau zu tun?
Wieso spielt das hier eine Rolle?
Im Moment geht es darum, wir wollen einfach die Verbindung aufbauen,
wollen einen Prozeduraufruf machen und vielleicht noch einen, wollen
dann wieder abbauen.
Da gibt es dieses nette Diagramm, was in der Vorlesung drin ist, mit
dieser Kurve hier.
Hat jemand noch im Griff, was die Kurve darstellt?
Ja, ist im Prinzip genauso richtig, wie das, was vorher gesagt wurde.
Ich bin nur penetrant, ich störe mich an dem Begriff Übertragungsrate.
Wird bei TCP die Übertragungsrate kontrolliert?
Da kommt ein Kopfschütteln, was wird denn kontrolliert?
Anzahl Pakete...
Ja, schreibe ich mal da hin.
Ich habe mit dem Pro Sekunde so ein bisschen das Problem.
Also wenn wir hier mal uns irgendwie das Ding nochmal vor Augen
halten, haben wir doch hier das Netz, haben IP, haben TCP, da oben
drüber wollen wir jetzt RPC setzen, da ist die Anwendung und wir
grübeln gerade ein bisschen, was alles zur Leistungsunfähigkeit
beiträgt.
Wo in der ganzen Geschichte wird denn die Übertragungsrate bestimmt
durch was?
Oder der Durchsatz, den sie erzielen können?
Können sie das da oben regeln, wenn sie da oben jetzt sagen 30
Megabit?
Haut das hin?
Ne, wohl kaum, wenn sie da unten eine 64 Kilobit Leitung haben.
Was sie hiermit regeln, sind die Anzahl Pakete, die sie senden dürfen,
bevor sie wieder eine Quittung kriegen müssen.
Was sie damit regeln, ist das Staukontrollfenster.
Das ist ein Unterschied, wenn sie aufpassen.
Aber die Auswirkung ist natürlich schon, dass sie hier erstmal relativ
wenig Daten senden dürfen, bis sie sich hochgeschaukelt haben zu einer
bestimmten Größe.
Wenn ich immer eine Verbindung verwende und multiplexe, dann
verhindere ich zumindest, dass ich unbedingt in diesen Slow-Start
reinfalle.
Natürlich kann er trotzdem zuschlagen, nämlich dann, wenn ihr Netz
einen Stau hat.
Und dann muss er auch zuschlagen.
Okay, soweit zu den allgemeinen Dingen.
Jetzt zu CORBA, was eine objektorientierte Umsetzung dieses Prinzips
ist.
Ist also objektorientiert, im Gegensatz zum ersten prozedurbasierten
Ansatz, den man mit RPC entwickelt hat, der heute aber auch noch
vielfach einfach vorhanden ist.
Es hat zum Ziel, eine universelle Mittelwelle zu sein, wobei es
inzwischen unterschiedliche Ausprägungen von CORBA gibt.
Realzeittauglich, nicht realzeittauglich, Embedded, nicht Embedded und
so weiter.
Wichtig ist, das ganze Ding ist sprachunabhängig.
Das heißt, ich kann in unterschiedlichen Sprachen auch Teile meiner
verteilten Anwendung realisieren.
Und plattformunabhängig.
Das heißt, wieder unabhängig von dem, was ich unten als Betriebssystem
beispielsweise drunter habe.
Entwickelt ist das ganze von einem Industriekonsortium.
Das heißt, es ist jetzt ganz klar ein Schritt gewesen, dass die
Hersteller aufeinander zugegangen sind und gesagt haben, wir wollen
gemeinsam eine Lösung finden für das Problem, die auch operabel auf
unterschiedlichen Plattformen ist und die offen dargelegt wird, im
Gegensatz zu den Aktivitäten eben Microsoft, die ihre eigene Schiene
gehen.
Wichtig dazu, freizugängliche und kostenlose Spezifikationen.
Das ist der Schlüssel, wie sie grundsätzlich solche Systeme ins Leben
reinbringen.
Weil sie damit erstens eine breite Plattform an Implementierern
finden, weil sie damit Ressourcen beispielsweise aus dem
Forschungsbereich, aus dem universitären Forschungsbereich nutzen
können, die typischerweise nicht Zehntausende von Euros oder so für
Spezifikationen ausgeben können.
Das Ganze, ja, Ende der 80er Jahre angefangen, in verschiedenen
Varianten, inzwischen relativ ausgereift als Middleware verfügbar.
Irgendwie sind in diesem Industriekonsortium so was um die 700, 800
Mitglieder relativ schnell drin gewesen.
Das heißt, es ist wirklich was, wo die Welt mit dran gearbeitet hat.
Was ist der grundsätzliche Ansatz, was sich wiederfindet, und das ist
in fast allen Systemen bis heute, sie haben irgendwo dieses kleine
Serverparadigma, das heißt, wir haben wieder einen Dienstnehmer, einen
Dienstgeber, die auch in ihrer Rolle unterschieden werden.
Dann ist das Ganze objektbasiert, was auch eine typische Konsequenz
war.
Entwicklung Ende der 80er Jahre, da war die objektorientierte Welt
einfach vorhanden.
Anfang der 80er beim RPC war das eben noch nicht der Fall.
Wichtig ist, dass bei den Objekten und bei der Definition klar
zwischen Schnittstelle und Implementierung getrennt ist.
Das heißt, sie spezifizieren Schnittstellen, unabhängig jetzt mal von
der Implementierung.
Die Objekte haben diese definierten Schnittstellen und führen dann
eben irgendwo die Requests, also die Aufrufe aus.
Das gleiche Prinzip, was dem RPC zugrunde liegt.
Es gibt verschiedene Möglichkeiten, jetzt entfernt Objekte aufzurufen.
Das ist einmal die synchrone Variante, die wir beim RPC als typisches
Muster gesehen haben.
Es ist die asynchrone Variante, die im Prinzip Richtung Message
-Oriented Systems geht.
Wo sie also einen Aufruf absetzen, aber nicht tatsächlich auf eine
Antwort warten.
Und es ist der verzögert-synchrone Bereich, wo sie eben weiterarbeiten
können und zu irgendeinem Zeitpunkt sich dann die Antwort abholen.
Also die drei unterschiedlichen Varianten, unterstützt von Korban.
Dann haben wir es jetzt mit Objekten zu tun, die eben in Anspruch
genommen werden.
Das heißt, wir müssen die irgendwie identifizieren können, damit wir
klar machen können, welches Objekt in der großen, weiten Welt wollen
wir denn aufrufen.
Das ist die Aufgabe von Objektreferenzen.
Das ist im Prinzip das gleiche wie die Adressierung wieder in der
Datenübertragung, die Sie auf unterer Ebene schon mal kennengelernt
haben, nur jetzt in den Anwendungsbereich übertragen.
Das heißt, Sie haben dann im Wesentlichen eben zwei Bestandteile von
so einer Objektreferenz.
Einmal müssen Sie auf einem System, wo Sie verschiedene Objekte drauf
haben, die Objekte unterscheiden können.
Dafür gibt es Objekt-IDs, die lokal gültig sind.
Wenn wir jetzt zur Datenübertragung unten das Pendant dazu suchen, was
wäre denn das Pendant dazu?
Also einmal hier eine lokale Objekt-ID, mit der ich so ein Objekt
lokal identifizieren kann.
Was würden Sie denn als Pendant der Datenübertragung nennen?
Ich versuche das nur mal irgendwo zusammenzubringen, damit Ihnen klar
wird, dass die Konzepte eigentlich immer ähnliche sind, die angewendet
werden.
Also nicht die Welt wieder neu erfindet, noch gar nicht muss.
Was haben Sie denn in Ihrem Stack an
Adressen zur Verfügung?
IP-Adressen, ja.
Und?
Session-Managements von TCP, damit meinen Sie was?
Ich habe es akustisch jetzt nicht so ganz verstanden, nur irgendwas
von Nummer noch mitgekriegt.
Es scheint seinen Sinn zu haben, dass wir hier ein Mikrofon benutzen.
Sie haben ja einmal Ports, das sind wahrscheinlich die Nummern, hoffe
ich doch, die Sie gemeint haben, die lokal eindeutig sind.
Dann haben wir hier die IP-Adressen, die jetzt das System oder den
Zugang identifizieren.
Und genauso brauchen Sie hier jetzt lokale Object-IDs und Sie brauchen
dann nochmal eine globale Referenz, die Sie zusammenpacken und dann zu
der Objektreferenz zusammenschustern.
Wichtig ist, dass der Client darauf natürlich keinen Einfluss hat.
Die Objektreferenz wird beim Server vergeben.
Dann gibt es auf Server-Seite sogenannte Servants, die eben jetzt
wichtig für die Realisierung der Korberobjekte sind, die gleichzeitig
ein oder mehrere Korberobjekte umfassen können und deren Zuordnung,
also Korberobjekt zu einem solchen Servant, sich zeitlich dann ändern
kann.
Das werden wir gleich nochmal am Beispiel sehen.
Hier ist nochmal kurz aufgezeichnet, wie der Ablauf jetzt mit den
Objekten ist.
Das ist im Prinzip die gleiche Fragestellung wie bei Prozeduren,
deswegen gehe ich da jetzt ein kleines bisschen schneller drüber.
Sie haben eben die Objekte in den verschiedenen Adressrollen, das
sollen die Dinger hier darstellen,
die adressierbar sind, wo wiederum beim Aufruf eben Datenformate
unterschiedlich sein können, andere Fehlerdomäne und so weiter.
Das hier analog natürlich zu den Problemen, die wir beim
Prozeduraufruf haben.
Was Sie wissen müssen, ist klar, Sie müssen Schnittstelle von dem Teil
kennen, um es aufrufen zu können.
Sie müssen die Objektreferenz kennen, um das ganze Ding aufrufen zu
können.
Und Sie brauchen noch sowas wie ein Wireprotokoll, so wird es
zumindest im Mittelwehrjargon bezeichnet.
Das heißt ein Protokoll, mit dem Sie tatsächlich die Kommunikation
hier abwickeln.
Ein Protokoll, das haben Sie am Anfang gelernt, sind ein paar stupide
Regeln, die schlicht und einfach vorschreiben, wie geht es.
Und wir werden noch irgendwie vorschreiben müssen, naja, was ist das
Datenformat, was wir da verwenden.
Ansonsten funktioniert das ganze genauso, Sie müssen halt die
Verbindung herstellen, Aufrufparameter verpacken, Marshaling, dann das
ganze schicken, der Drüben packt es aus, ruft die Methode auf, das
ganze Ergebnis wird wieder eingepackt und so weiter.
Das ist also ein relativ gleicher Vorgang hiervon.
Jetzt kommt eben die Sache mit dem Servant hier nochmal ins Spiel.
Zum einen brauchen Sie hier wieder die beiden Sachen Stub und
Skeleton, die eben sozusagen Ihre Aufrufe an das entfernte Objekt
weiterreichen.
Marshaling und Demarshaling machen.
Und dann haben Sie noch die Möglichkeit der Realisierung hier drüben.
Die haben eben die sogenannten Servants, in denen dann auch mehrere
Objekte drin residieren können.
Das sind hier am Anfang nochmal die gleichen Sachen,
Verteilungstransparenz, Ortstransparenz, wie wir sie eben schon
gesehen haben.
Fehler müssen Sie sich in Erinnerung rufen und dann die jeweilige
Semantik, mit der Sie arbeiten.
Ein Problem, was ich vorhin noch nicht angesprochen hatte, die
Erzeugung und Zerstörung von Objekten.
Wenn Sie auf der Seite sind, also auf der Client-Seite, haben Sie
natürlich zunächst mal keinen Einfluss drauf, was mit Objekten hier
auf der Server-Seite passiert.
Das heißt, Sie können die nicht wirklich erzeugen, aktivieren und so
weiter.
Das kann im Prinzip implizit passieren, durch den Methodenaufruf
getriggert.
Auf der anderen Seite müssen die Objekte als solche, wenn Sie sie hier
aufrufen können wollen, natürlich irgendwie bekannt sein mit ihrer
Referenz, ihrer Schnittstelle.
Das heißt, sie müssen irgendwo verzeichnet sein.
Wie macht man es typischerweise?
Es gibt ein sogenanntes Fabrikobjekt.
Der Name kommt wohl irgendwie daher, weil das Objekt nichts wirklich
Sinnfälliges für die Anwendung macht, sondern einfach nur so vor sich
hinschafft, um andere Objekte zu erzeugen und wieder zu zerstören.
Das heißt typischerweise wird so ein Fabrikobjekt, wir werden das
nachher auch nochmal an einem Beispiel sehen, nächsten Donnerstag,
einfach zunächst mal aufgerufen werden, um das eigentliche Objekt zu
erzeugen.
Dann wird dieses Objekt in Anspruch genommen und wenn das Objekt
zerstört werden soll, läuft es eben genauso wieder über das
Fabrikobjekt.
Was man dann noch beachten muss, ist natürlich, wenn ich das Objekt
zerstöre, ist nicht unbedingt der Stub auch weg.
Das heißt, auch den muss ich irgendwie zerstören können, damit ich
nicht nachher damit ende, dass ich eine Reihe von Stubs rumliegen habe
und keine dazugehörigen Objekte.
Die Parameterübergabe habe ich natürlich genauso wie die Problematik
beim RPC.
Wie sieht jetzt das Korba-Teil aus, wenn man es sich von der
Architektur ein bisschen anschaut, nämlich die Referenzarchitektur,
also die OMA, die man dazu spezifiziert hat.
Dann kommt man zu diesem Bildchen, was hier drauf ist, was sozusagen
auch die Produkte dieser Object Management Group ist, die sich eben um
die Standardisierung von Korba kümmert.
Zum einen habe ich das Objektmodell, wo es um die Objektschnittstellen
geht und zum anderen habe ich eben dieses Referenzmodell hier, was aus
einer Reihe von wichtigen Komponenten besteht.
Das Herz der ganzen Sache ist der Object Request Broker.
Und der macht jetzt ein bisschen mehr als einfach nur einen Socket
-Aufruf, das Ding drüberleiten und die Antwort zurückleiten.
Der ist für die ganze Vermittlung der Kommunikation verantwortlich.
Das heißt auch für das Finden der Objekte etc.
pp.
Der ist also das Herzstück einer Korba-Mittelwehr.
Man könnte sich das vereinfacht so darstellen, wenn Sie ein Client
-Objekt haben, dann geht der Aufruf eben hier über den Orb rüber zu
dem wahrscheinlich nicht mehr lesbaren Server-Objekt hier.
Das heißt, das ist sozusagen Ihr Kommunikationssystem, das Sie auf
dieser Ebene sehen.
Dass in diesem Orb nach innen drin irgendwann TCP, IP und sowas drin
ist, bleibt Ihnen alles transparent.
Es gibt dann Korba Services, die angeboten werden, die eben jetzt
allgemeingültige Dienste darstellen, die sozusagen jeder Benutzer von
so einer Plattform benötigt.
Dazu gehören Dinge wie ein Trader, ein Vermittler, der mir jetzt
Dienste findet.
Es gehören Namensdienste dazu, Persistenzdienste werden wir kurz
sehen.
Lifecycle, das ist die Sache mit dem Lebenszyklus, also erzeugen,
aktivieren, löschen der Objekte, das ist das, wo das Fabrikobjekt
nachher ins Spiel kommt.
Und eine ganze Reihe anderer Dienste, die da zur Verfügung stehen.
Wie gesagt allgemeingültig, die für die verschiedenen Anwendungen
nutzbar sein sollen.
Die Korba Facilities, die Horizontalen, damit sind solche
Anwendungsdienste gemeint, wie meinetwegen Druckdienst.
Also auch wieder was relativ generisches, was bereitgestellt wird.
Darüber hinaus gibt es dann die Korba Facilities, das sind vertikale
Lösungen, wo Ihnen komplette Branchenlösungen wie Finanzdienste,
Medizindienste etc.
zur Verfügung gestellt werden.
Und dann gibt es Application Objects hier, die eben jetzt tatsächlich
beispielsweise die Infrastruktur nutzen können, die aber nicht von
Korba irgendwo standardisiert werden.
Was spezifiziert Korba jetzt in dem ganzen Bereich?
Einmal das Objektmodell, und zwar ein abstraktes Objektmodell, was
jetzt nichts mit ihrem Implementierungsmodell zu tun hat.
Das ist eine Abstraktionsstufe weiter oben.
Dann brauchen wir eine Schnittstellenbeschreibungssprache, mit der wir
jetzt die Schnittstellen der Objekte beschreiben können.
Die ist standardisiert und die wird nachher in die Programmiersprache
übersetzt.
Und das können Sie in unterschiedliche Programmiersprachen übersetzen.
Unterstützt wird eine ganze Reihe von Dingen, auf jeden Fall die
gängigen C, C++, Java usw.
Es gibt ein Wire-Protokoll, was eben jetzt für die Kommunikation auf
der Ebene verantwortlich ist.
Wenn Sie sich wieder Ihren Stack hier reinholen.
Wir sitzen jetzt hier oben drauf und spezifizieren hier ein Protokoll,
was auf Anwendungsebene operiert.
Und die normalen Übertragungsdienste, die Sie vorher schon
kennengelernt haben, einfach nutzt.
Dann gibt es klare Schnittstellen zum Object-Request-Broker, weil der
ist hier Ihre Zentrale, an die Sie eben ran müssen, wenn Sie
kommunizieren wollen.
Das gibt es sowohl auf der Client- als auch auf der Serverseite, wo
Sie dann irgendwelche Servants zum Beispiel registrieren und
aktivieren können, sodass die überhaupt nach außen sichtbar sind.
Und dann hat man darauf geachtet bei der Entwicklung, weil zu dem
Zeitpunkt, als man das angefangen hat, war es natürlich nicht die
einzige Richtung, die man gegangen ist.
Es ist aber jetzt schlicht und einfach das Produkt, das überlebt hat.
Man hat ebenfalls darauf geachtet, dass man mit anderen Standards
relativ interoperabel ist.
So, was macht jetzt der Object-Request-Broker, was man vorher nicht
getan hat, was meine TCP-IP-Verbindung mir nicht leisten kann?
Zum einen kann ich Ressourcenverwaltung damit unterstützen.
Das heißt, ich weiß über die Verfügbarkeit von Ressourcen Bescheid.
Ich kann Netzverbindungen multiplexen, muss also nicht immer einzelne
TCP -Verbindungen verwenden, mit dem Vorteil, den wir vorhin schon mal
gesagt hatten.
Ich kann die Skeletons und Servants aktivieren bei Bedarf, was ja
automatisch so nicht passiert.
Dann werden Bibliotheksroutinen für Marshalling und Demarshalling
bereitgestellt.
Das ist etwas, was sie typischerweise nicht implementieren.
Da haben sie ein Bibliotheksstück, was sie eben mit verwenden.
Und es gibt Schnittstellen für weitere neue Dienste, die sie dazu
binden können.
Weil das ist ja letztendlich auch ein Ziel.
Ich will das erweitern können, wenn ich neue Dienste brauche.
Ja, das da unten wiederholt die Geschichte eigentlich jetzt nur
nochmal.
Was für Begriffe muss man sich noch anschauen?
Welcher der Begriffe fasziniert Sie denn so?
Aha, weshalb?
Sie bezweifeln die Sinnfälligkeit einer Verschlüsselung.
Weshalb?
Ja, es ist nicht der Servant, der verschlüsselt, aber sie wollen sie
vielleicht verschlüsseln, bevor sie sie loswerden.
Also die Idee ist, dass sie hier verschlüsseln, bevor sie die Daten
hier nachher raussenden.
Das würde ich behaupten, gibt es durchaus die ein oder andere
Anwendung, wo das machen können wollen.
Muss man dann wohl machen, ja.
Wo waren wir denn?
Okay, was gibt es?
Genau, was haben wir?
Wir haben einmal die Objekte selber.
Die jetzt die Entitäten sind, die eigentlich das Problem lösen.
Die eine eindeutige Identität haben und einen Zustand.
Servants sind jetzt die Teile, die die Korba-Objekte inkarnieren.
Das heißt, die sie wirklich tatsächlich aufrufbar machen.
Sprich, ein Korba-Objekt muss immer mit einem Servant verbunden sein,
um aufrufbar zu sein.
Und ein Servant kann in seiner Lebenszeit natürlich mehrere solche
Objekte besitzen.
Wenn ein Objekt nur einmal dem Servant zugeordnet wird und dann wieder
gelöscht wird, haben sie ein transientes Objekt.
Wenn das Objekt selbst jetzt dann eben wieder deaktiviert wird, aber
seinen Zustand behält und dann wieder von einem Servant inkarniert
werden kann, dann reden wir von persistenten Objekten.
Es gibt also in dem Fall sowohl transiente als auch persistente
Objekte.
Bei so einem persistenten Objekt kann man sich einfach vorstellen,
dass der Zustand zugehörig zu diesem Objekt beispielsweise auf einer
Datenbank abgelegt wird und bei der neuen Inkarnierung dann wieder
restauriert wird und dann kann das Objekt auch wieder aufgerufen
werden von irgendeinem Dienstnehmer.
Die Objektadapter sind jetzt dafür zuständig, welcher Servant zu
welcher Objekt-ID zugeordnet wird.
Die Referenzen hatten wir schon und die Policies geben eben schlicht
und einfach an, nach welcher Strategie ich beispielsweise die Servants
zuordne.
Wieso machen solche Objektadapter Sinn?
Ganz einfach deshalb, weil man damit versucht, den Kern von KORBA,
also das, was man als Mittelwert zur Verfügung stellt, vom
objektspezifischen Verhalten unabhängig zu machen.
Das heißt, sie sind im Kern zunächst mal möglichst generisch, bauen
sich eine Schnittstelle dazwischen und was nachher obendrüber
objektspezifisch abläuft, halten sie aus dem Kern raus.
Kann man sich streiten, ob das Sinn macht oder nicht, aber der große
Vorteil ist, sie kriegen einen relativ kleinen oder einen kleineren
Kern dadurch und erhöhen damit auch die Flexibilität.
Objekt-ID und Objekt-Referenzen hatten wir irgendwie schon mal.
Das ist für Sie vielleicht jetzt gerade ein bisschen merkwürdig, wenn
dann so gelegentlich mal was zwei oder dreimal auf einer Folie
auftaucht.
Das ist meistens die Phase, wo wir Dozenten, wenn wir das zum zweiten
Mal halten, werden die Folien anders aussehen.
Die sehen nächstes Jahr garantiert anders aus und übernächstes Mal
wieder.
Das ist nämlich so ein bisschen der Punkt, wo man sich selber erst mal
zurechtdrüttelt.
Was erklärt man denn wo und wie vermeidet man, dass man Dinge zu oft
oder zu wenig oft erläutert.
Wird Ihnen nicht anders gehen, wenn Sie Seminarvorträge halten und
dann plötzlich dastehen, den Vortrag halten und denken, man hat sich
wohl bei der Folie gedacht, die passt gar nicht mehr in den Fluss
rein.
Das erleben Sie hier gerade ein bisschen, weil das in der Tat der Teil
für dieses Semester zum ersten Mal ausgearbeitet worden ist.
Den hatten wir vorher in der Vorlesung nicht drin.
Was tun die Objektadapter jetzt?
Die sind eben verantwortlich für das Verwalten der Objekte.
Dazu erzeugen sie die ObjektID, die Objektreferenz, die kommt vom ORB.
Das heißt, so ein Objekt kriegt einmal vom Adapter die ID zugewiesen
und vom ORB die Referenz, also den Nicht-ID-Teil von der Referenz.
Und der Objektadapter begleitet sozusagen den Lebenszyklus von dem
Objekt.
Ist also für aktivieren, deaktivieren, zerstören und sowas
verantwortlich und auch für das Durchführen der Methodenaufrufe
letztendlich.
Es gibt sogenannte Portable Object Adapters.
Oder fangen wir mal noch eins vorher an.
Sie machen Objektadapter.
Wie machen Sie sie denn eigentlich?
Die Frage, die man sich dann relativ schnell gestellt hat, war, naja,
lasst uns mal so einen Basis-Objektadapter entwerfen, der so alles
kann.
Den hat man Basic Object Adapter genannt, BOA abgekürzt.
Über den stolpern Sie gelegentlich auch noch in der Literatur.
Den hat man dann irgendwann wieder begraben und hat gesagt, jetzt
lasst uns die Sache mal richtig tatsächlich machen und lasst uns einen
sozusagen Allzweck-Objektadapter realisieren.
Mit dem wir vor allem auch Portabilität zwischen unterschiedlichen
Implementierungen bereitstellen können.
Denn was ja passieren kann ist, Sie haben hier ein System, das hat die
CORBA Implementierung 1 und hier ein System, das hat irgendwie die
CORBA Implementierung 2.
Wie kriegen Sie Interoperabilität da zustande?
Das ist die Aufgabe im Prinzip von diesen Portable Object Adapters,
die flexibel sein sollen, möglichst von dem Anwender eben auch
konfigurierbar sein sollen.
Und was hat man letztendlich gemacht?
Man hat eine Hierarchie von POAs sozusagen, designed mit einem Root
-POA, also einem Wurzel-POA, das man dann eben verfeinern kann.
Mit dem man verschiedene Policies zuordnen kann, die jetzt
beispielsweise das Verhalten von diesen Dingen steuern und die Dinge
wie Persistenz etc.
PP unterstützen können.
Persistenz werden wir uns Donnerstag nochmal anschauen.
Wie sehen die Dinge aus?
Die sind im Prinzip erstmal nicht sichtbar für die Clients, das heißt
der Client hat hier seine Objektreferenzen.
Damit geht er jetzt auf den Server hier rüber.
Der Server hat irgendwie seine Servants, die jetzt tatsächlich eben
inkarnierte Objekte auch beinhalten.
Also hier zum Beispiel dieses Teil und dieses Teil.
Und er hat hier vorne seinen Objektadapter und hier in dem Fall jetzt
zwei Stück.
Zwei solche Portable Object Adapters A und B.
Und wenn er eben jetzt hier auf den Korba-Server hier rüber will, gibt
er an welchen Objektadapter er ansprechen will und dann vor allem
welches nicht mehr sichtbare.
Kriegt man das eigentlich wieder irgendwie weg?
Die nicht mehr sichtbare ID 29, das heißt er will im Prinzip auf
dieses Objekt hier und geht über diesen Portable Object Adapter
darüber.
Ja, wie sehen die Kernkomponenten jetzt aus, wenn man es sich nochmal
ein bisschen weiter aufdröselt?
Das Herz, immer noch der Orb, das wird es auch bleiben.
Wir haben hier ein paar Wireprotocols, hier hinten dran, mit denen
dann kommuniziert wird.
Und ein Verzeichnis, in dem jetzt die Schnittstellen der Objekte
registriert werden können.
Dann haben wir hier den Dienstnehmer, also den Client und den Server.
Sie können einmal über einen Stab drauf zugreifen.
Das ist dieses Teil hier, das jetzt das ganze Marshalling,
Demarshalling macht.
Das hat natürlich den Vorteil, dass Sie sich darum nicht so kümmern
müssen.
Das wird typischerweise eben automatisch realisiert.
Sie brauchen dann unten vom entfernten Objekt hier überhaupt kein
Wissen zu haben.
Sie schicken das Teil hier rüber, das geht über den Objekt Adapter.
Jetzt entweder auch in das Gegenpart von hier, das Skeleton rein, wo
das Demarshalling wieder gemacht wird.
Und dann können Sie hier auf das Dienstgeberobjekt zugreifen.
Es gibt eine direkte Schnittstelle, mit der Sie auf den Orb zugreifen
können und das Stab hier umgehen.
Was aber typischerweise nicht das ist, was man sicherlich verwendet,
wenn man eine verteilte Anwendung realisiert.
Und Sie können den Stab hier auch umgehen, indem Sie über dynamische
Aufrufschnittstellen hier gehen.
Dann ist aber die Transparenz zwischen Dienstnehmer und Dienstgeber
eben nicht mehr gewährleistet.
Da wollte ich eigentlich auch für heute Schluss machen.
Das Beispiel mache ich erst nächste Woche, weil das in der Tat Sachen
aussetzt, die eigentlich erst nächsten Donnerstag wirklich kommen.
Das heißt nächsten Donnerstag der zweite Teil von Korba und Sie sind
von mir zumindest ins Wochenende entlassen.
Ich bedanke mich.