State-of-the-Art

Über verschiedene Arten von State und welchen Einfluss diese auf unsere Cloud-Native Applikationen haben

Mirko Stocker
Cloud Solutions @ OST

--

Welche Eigenschaften zeichnen eine ideale Cloud-Native Applikation aus? In diesem Beitrag befassen wir uns mit dem Thema State und dessen verschiedenen Ausprägungen.

Was ist überhaupt State? Wenn wir diese Frage einer Netzwerkingenieurin stellen, dann wird sie vielleicht etwas über die verschiedenen Zustände von TCP/IP und vom Übergang von einem Zustand in einen anderen erzählen. Ein Webentwickler wird antworten, dass HTTP keinen Zustand hat, also ein stateless Protokoll ist. Aus Sicht eines Programms umfasst der Zustand den Inhalt aller Variablen und wo in der Ausführung das Programm sich gerade befindet. Wir wollen State heute aus Sicht des Cloud-Architekten betrachten.

Key Takeaways

  • In Applikationen entstehen verschiedene Arten von State: Resource State entsteht aus den Informationen, die die Applikation verwaltet. Session State hingegen tritt während der Kommunikation mit und zwischen Teilen der Applikation auf.
  • Applikationskomponenten sollen stateless sein, besonders jene, die horizontal skaliert werden.
  • Mit einer Kombination aus Client Session State und Database Session State werden die serverseitigen Applikationskomponenten stateless.

Ganz egal, ob wir uns in der Cloud bewegen oder nicht, eine Applikation verwaltet typischerweise auch Daten. Aus diesen Daten ergibt sich eine erste Art von State, den wir Resource State⁰ nennen. Mit der Verwendung der Applikation verändern sich auch diese Daten und entsprechend der Gesamtzustand der Applikation über die Zeit.

Daneben gibt es auch noch den sogenannten Session State¹. Zum Session State gehört beispielsweise der Zustand der Kommunikation zwischen Client-Frontend und Server-Backend. Ein klassisches Beispiel dafür ist der Warenkorb eines Onlineshops. Solange die Bestellung noch nicht aufgegeben wurde, muss der Inhalt des Warenkorbs nicht für immer gespeichert werden und verfällt, wenn der Benutzer die Seite verlässt. Session State verfällt also und kann dann entfernt werden².

Client-Server Architektur mit drei Tiers.

Wird die Bestellung dann aufgegeben, verändert sich der Resource State. Die zur Bestellung gehörenden Daten müssen vom System dauerhaft gespeichert werden und lösen einen Bestellprozess aus. Auch die Angaben zu den Artikeln, die der Shop anbietet, gehören zum Resource State. Die Art von Daten also, die klassisch in einer relationalen Datenbank, wie zum Beispiel PostgreSQL oder SQL Server, abgelegt werden.

Im Kontext von Cloud Computing ist es nun wichtig, dass wir State nicht unnötig überall verteilen. Wir gehen sogar so weit und sagen, dass wir Stateless Server haben wollen. Nur wie soll das gehen? Ohne State liesse sich ja nicht mal ein Onlineshop in der Cloud betreiben! Tatsächlich meinen wir damit, dass zwischen mehreren Requests kein State aufbewahrt wird und wir jeglichen Zustand ausserhalb unserer serverseitigen Applikationskomponenten ablegen. Es darf sehr wohl mit State gearbeitet werden, dieser muss aber falls nötig rekonstruiert werden können, ohne dass Clients dies bemerken würden.

Ein stateless Server speichert keinen State.

Weshalb sollen wir uns so eine Einschränkung auferlegen? Ein Vorteil von OSSM-Clouds ist, dass die verwendeten Ressourcen skalierbar sind. Wir können also die Anzahl Backends der momentanen Auslastung des Systems anpassen:

Instanzen von Backend-Komponenten können zu- und abgeschaltet werden. Ein Loadbalancer verteilt die Anfragen der Clients an die Backends.

Allerdings haben wir nun ein Problem: Wie können wir sicherstellen, dass der Client zu seinem Warenkorb in “seinem” Backend gelangt? Das könnte der Loadbalancer übernehmen, aber falls ein Backend nicht mehr da ist (abgestürzt, temporär nicht erreichbar oder regulär herunterskaliert) sind die Daten weg. Eine Möglichkeit wäre, den Zustand zwischen den Backends zu synchronisieren. Aber dann ist es vielleicht einfacher, die Backends gleich stateless zu machen und den Session State in die Datenbank auszulagern³.

Stateless Server mit Database Session State. Auch der Client hat ein kleines Stückchen State, z.B. eine Session-ID oder Token, welcher bei jedem Request als Cookie oder im Header mitgeschickt wird, um die Session zu identifizieren.

Unsere Backends sind nun Stateless Components, wie dieses Cloud Computing Patterns genannt wird. Wird der State zwischen den Komponenten stattdessen synchronisiert, dann würden wir von Stateful Components sprechen.

In unserem Warenkorbbeispiel besteht der Zustand aus komplexen Daten,⁴ und diese in einer Datenbank abzulegen ist naheliegend. Aber es gibt auch Session State, der nur beim Client verbleiben kann. Nehmen wir an, wir konzipieren eine Applikation für Meinungsumfragen. Die Umfragen bestehen aus mehreren Seiten, die jeweils aufgrund der bisherigen Antworten ausgewählt werden.

Auszug der Konversation zwischen Front- und Backend.

Im klassischen Ansatz mit Server Session State würde sich das Backend merken, auf welcher Seite sich der Client gerade befindet und welche Fragen als nächstes an der Reihe sind. In einer Applikation mit clientseitiger Programmlogik, zum Beispiel einer modernen Single Page Application, kann auch der Client diese Aufgabe übernehmen. Der Server teilt dem Client in seiner Antwort mit, welche nächsten Schritte möglich sind. Der Client kann dann entscheiden, wie er fortfahren möchte. (Genauso, wie auch wir Menschen mit einer Webseite interagieren: wir landen auf einer Seite und bewegen uns dann über die von der Seite angezeigten Links und Formulare durch die Seiten.)

Dieser Ansatz, also dass der Server die Möglichkeiten vorgibt und der Client auswählt, nennt man auch hypertext-driven und ist eine der Regeln des Representational State Transfer Architekturstils, besser bekannt unter dem Akronym REST. REST gibt unter anderem eine Antwort auf die Frage, wie in einer verteilten Applikation Aktionen auf Ressourcen ausgeführt werden können. Wird eine Ressource von einem Client angefragt, antwortet der Server mit einer Repräsentation des aktuellen Resource States (man könnte auch Snapshot sagen), zusammen mit Metadaten, die angeben, wie der Zustand der Ressource verändert werden kann. Der Client kann dann seine Repräsentation der Ressource anpassen und über den kommunizierten Weg wieder an den Server transferieren. Dadurch, dass die Daten mitgeschickt werden — man spricht auch davon, dass die Anfragen self-contained sind — kann der Server wiederum stateless sein.

Zu REST liesse sich noch viel sagen, zum Thema REST und State empfehlen wir Gregor Hohpes RESTful Conversations zu lesen. Bei ihm gibt es auch den Begriff des Conversation States, eine Variante des Session States.

Um unsere bestehenden Applikationen cloud-ready zu machen müssen wir wissen, ob Server Session State verwendet wird. Eventuell lässt sich dieser auslagern und wir erhalten eine Stateless Component. Geht das nicht, bietet das Framework womöglich eine Lösung um Sessions zu replizieren, wie zum Beispiel Spring Session.

Legen wir den Session State in einer Datenbank ab, kann es sich lohnen, eine spezielle Key-Value Datenbank wie Redis zu wählen, die genau für diesen Einsatzzweck optimiert ist. Man sollte aber auch immer ein Auge auf die zusätzliche Komplexität haben, die man sich dadurch einfängt und entsprechend abwägen.

Beim Einsatz von Client Session State dürfen Sicherheitsüberlegungen nicht fehlen: eine Session-Id oder ein Token sollte geschützt werden — also nur per HTTPS übertragen werden — und schwer zu erraten sein. Dieses Cheatsheet von OWASP erklärt, was man beachten sollte. Auch Clients kann man nicht uneingeschränkt vertrauen: modernes HTML und Single Page Applications erledigen die Inputvalidierung elegant auf dem Client, trotzdem muss auch serverseitig validiert werden. Und zu guter Letzt: Zustand, der nicht übertragen wird, kann auch nicht manipuliert werden.

Weiterführende Links

⁰ Oft wird dafür auch der Begriff Application State verwendet. Application State kann aber auch als Überbegriff mit den Ausprägungen Session State und Resource State verstanden werden. Andere wiederum nennen das, was wir als Session State bezeichnen, Application State. Deshalb scheint uns die Wahl von Resource State unmissverständlicher.

¹ Martin Fowler widmet Session State Patterns ein ganzes Kapitel in Patterns of Enterprise Application Architecture.

² Zugegeben, von einem modernen Onlineshop erwarten wir, dass er den Warenkorb noch ein bisschen länger speichert. Aber wir wurden bestimmt alle schon beim Onlineshopping abgelenkt und mussten dann verärgert feststellen, dass der Warenkorb plötzlich wieder leer war. Das andere Extrem sind Shops, die einem E-Mails senden, dass man noch was im Warenkorb vergessen habe.

³ Wir müssen uns jetzt aber auch um das Aufräumen kümmern und eventuell den Warenkorb auch mal wieder löschen. Oder dem Kunden vielleicht eine Erinnerungsmail senden, sofern wir denn diese Angaben haben.

⁴ Neben den Hinweisen zum Produkt könnte es auch nötig sein, den aktuellen Preis im Warenkorb abzulegen um später den Kunden auf eine allfällige zwischenzeitliche Veränderung im Preis hinzuweisen. Gerade wenn der Warenkorb über eine längere Zeit hinweg bestehen bleibt, kann das durchaus vorkommen.

--

--

Mirko Stocker
Cloud Solutions @ OST

SE Prof (Cloud, Web, Programming Languages) @ OST; Partner @ Institute for Software; Co-Founder @ LegalGo