Nachdem ich mich in den letzten Tagen irgendwie mehr wieder Services und Service-Strukturen
gedanklich beschäftigt habe (in Staus hat man viel Zeit für so etwas), habe ich mal angefangen in paar kurzen Gedanken zusammen zu fassen, wie ich mir eine Umgebung vorstelle, mit der man sehr flexibel und fehler-tollerant arbeiten und entwickeln kann.
Es geht hier hauptsächlich um REST-Services, die man z.B. von einer AngularJS Anwendung oder einen Java-Desktop-Client Aufruft. Oder auch REST-Services die zwischen Servern zur Kommunikation verwendet werden.
Wichtig dabei ist auf jeden Fall, dass man Config-Dateien an einem separaten Ort ablegen kann. Also getrennt vom Service-Code, so dass man ohne Probleme eine neue Version deployen kann, ohne sich darum Gedanken machen zu müssen, ob man die Config überschreibt oder eine für ein falsches System darin enthalten sein kann. Die Anpassung des Services wird extern von der Umgebung gemanagt.
Sollte keine eigene Config-Datei vorhanden sein, sollte der deployte Service mit default Einstellungen laufen.
Die Umgebung sollte einen Service deployen, undeployen und pausieren können. So dass man einen Service für Wartungen deaktivieren kann und das System Anfragen entweder so lange hält (bis der Service wieder da ist oder eine Timeout kommt) oder eine allgemeine Antwort zurück liefert, die dem Anfragenden darüber informiert, dass der Service zur Zeit nicht verfügbar ist.
Es sollte auch ein Reload eines Services möglich sein, um z.B. geänderte Config-Daten zu erkennen. Da würde ja ein Call auf eine Methode des Service-Objekts reichen, dass in einem bestimmten Interface vorgegeben wird.
Wenn man eine große Anwendung hat, muss man früher oder später die Services auch untereinander kommunizieren lassen. Konzept wie @ejb halte ich für zu unflexibel, da man direkte Pfade und so berücksichtigen muss. Ein Service sollte intern einen selbst gewählten eindeutigen Namen haben. Der alleine reicht um einen Service anzufordern. Da wird dann aber auch nicht ein Interface un eine Proxy-Klasse zurück geliefert sondern ein Descriptor-Objekt, dass angibt ob der Service verfügbar ist und die Root-URL. Es müsste auch eine Version mit in der Anfrage nach dem Service sein, um zu verhindern, dass Dependencies ein nicht handhabbares Problem werden. Wenn man die Verfügbarkeit über das Objekt prüft, wird immer der aktuelle Status des Services ermittelt.
Man kann also Versionen abhängige Logiken implementieren, falls der eigene Service sich mit einer aktuelleren Version anders verhalten sein, weil die vielleicht eine bessere Methode für irgendwas hat. Sollte ein Service gar nicht vorhanden sein oder plötzlich offline gehen, muss man gucken, ob meinen Fehler zurück liefert oder eine Fallback-Lösung bemüht. Wenn man z.B. einen zentralen Logging-Service verwendet und dieser während der Laufzeit in den Wartungsmodus versetzt wird, könnte man für die Zeit auf eine eigene Datei-basierte Lösung zurück greifen, bis der Logging-Service wieder verfügbar ist.
Die Umgebung hat ein zentrales Verzeichnis mit allen deployten Services. Man könnte überlegen, dass dieses Verzeichnis die Request nicht nur auf die Objekte mapped sondern auch auf andere Server weiterleiten könnte, so dass man Services sogar über verschiedene Server verteilen kann,
aber für den Client weiterhin einen zentralen Aufrufpunkt hat.
Auch könnte man implementieren, dass ein Service eine asynchrone Nachricht an das System schickt und die Nachricht dann an jeden Service verteilt wird.
Wichtig wäre bei der Kommunikation zwischen Services auf jeden Fall, dass Requests es auch asynchron bearbeitet werden können. Also das z.B. bei unserem Logging-Service zwar die Verfügbarkeit geprüft wird dann aber nach dem Fire-And-Forget Prinzip weiter verfahren wird. Ansonsten ist es auf der Service-Seite gerade mit inter-Service Kommunikation es wohl meistens einfacher synchron zu arbeiten. Auf Client-Seite sollte man ja asynchron arbeiten, da es die UX sehr verbessert.
DataSources und Transaction-Management sollte auch von der Umgebung alles bereit gestellt und verwaltet werden. In der Config-Datei für einen Service trägt man dann ein "verwende DataSource 'CRM_ARTICLES'". Der Service alleine darf sich selbst keine Datenbankverbindungen erstellen.
Mit soetwas sollten sich auch größere Anwendungen mit getrennten Modulen/Services entwickeln lassen ohne zu schnell in Probleme zu laufen.. natürlich nur wenn man die Möglichkeiten nutzt und nicht versucht am System vorbei Dinge zu erledigen. Ob so ein System für solche Service-Module performant realisieren kann, müsste man einfach mal ausprobieren.. wenn man die Zeit dafür hätte. In Java sollte sich so etwas gut Umsetzen lassen. In PHP sehe ich viele Probleme, weil man keine zentralen Application-Scope oder so hat.
Comments are disabled for this blog-entry.