• Keine Ergebnisse gefunden

Reaktive Programmierung Vorlesung 13 vom 22.07.14: Robustheit, Entwurfsmuster und Theorie der Nebenläufigkeit

N/A
N/A
Protected

Academic year: 2022

Aktie "Reaktive Programmierung Vorlesung 13 vom 22.07.14: Robustheit, Entwurfsmuster und Theorie der Nebenläufigkeit"

Copied!
28
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

Reaktive Programmierung

Vorlesung 13 vom 22.07.14: Robustheit, Entwurfsmuster und Theorie der Nebenläufigkeit

Christoph Lüth & Martin Ring

Universität Bremen

Sommersemester 2014

(2)

Fahrplan

I Teil I: Grundlegende Konzepte

I Teil II: Nebenläufigkeit

I Teil III: Fortgeschrittene Konzepte

I Bidirektionale Programmierung: Zippers and Lenses

I Robustheit, Entwurfsmuster und Theorie der Nebenläufigkeit

(3)

Robustheit in verteilten Systemen

Lokal:

I Aktoren können abstürzen - Lösung: Supervisor Verteilt:

I Nachrichten können verloren gehen

I Teilsysteme können abstürzen

I Hardware-Fehler

I Stromausfall

I Geplanter Reboot (Updates)

I Naturkatastrophen / Höhere Gewalt

I Software-Fehler

(4)

Zwei-Armeen-Problem

A1 - B A2

-

-

I Unlösbar – Wir müssen damit leben!

I TCP: Drei-Wege-Handschlag + Nummerierte Pakete

(5)

Zwei-Armeen-Problem

A1 - B A2

-

-

I Unlösbar – Wir müssen damit leben!

I TCP: Drei-Wege-Handschlag + Nummerierte Pakete

(6)

Zwei-Armeen-Problem

A1 - B A2

-

-

I Unlösbar – Wir müssen damit leben!

I TCP: Drei-Wege-Handschlag + Nummerierte Pakete

(7)

Zwei-Armeen-Problem

A1 - B A2

-

-

I Unlösbar – Wir müssen damit leben!

I TCP: Drei-Wege-Handschlag + Nummerierte Pakete

(8)

Zwei-Armeen-Problem

A1 - B A2

-

-

I Unlösbar – Wir müssen damit leben!

I TCP: Drei-Wege-Handschlag + Nummerierte Pakete

(9)

Gossipping

N1 N2 N3 N4

N5 N6

N7 N8

N9 N10 N11 N12

(10)

Gossipping

N1 N2 N3 N4

N5 - N6

N7 N8

N9 N10 N11

-

N12

(11)

Gossipping

N1 N2 N3 N4

N5 - N6

N7 N8

N9 N10 N11

-

N12

(12)

Heartbeats

I Kleine Nachrichten in regelmäßigen Abständen

I Standardabweichung kann dynamisch berechnet werden

I Φ =−log10(1−F(timeSinceLastHeartbeat))

(13)

Akka Clustering

I Verteiltes Aktorsystem

I Infrastruktur wird über gossipping Protokoll geteilt

I Ausfälle werden über Heartbeats erkannt

I Sharding: Horizontale Verteilung der Resourcen

I In Verbindung mit Event-Sourcing sehr mächtig

(14)

(Anti-)Patterns: Request/Response

I Problem: Warten auf eine Antwort — Benötigt einen Kontext der die Antwort versteht

I Pragmatische Lösung: Ask-Pattern import akka.patterns.ask

(otherActor ? Request) map { case Response //

}

I Eignet sich nur für sehr einfache Szenarien

I Lösung: Neuer Aktor für jeden Response Kontext

(15)

(Anti-)Patterns: Nachrichten

I Nachrichten solltentypisiert sein

otherActor ! "add 5 to your local state" // NO otherActor ! Modify(_ + 5) // YES

I Nachrichten dürfennichtveränderlich sein!

val state: scala.collection.mutable.Buffer otherActor ! Include(state) // NO

otherActor ! Include(state.toList) // YES

I Nachrichten dürfenkeine Referenzenauf veränderlichen Zustand enthalten

var state = 7

otherActor ! Modify(_ + state) // NO val stateCopy = state

otherActor ! Modify(_ + stateCopy) // YES

(16)

(Anti-)Patterns: State-Leaks

I Lokaler Zustand darf auf keinen Fall “auslaufen”!

var state = 0

(otherActor ? Request) map { case Response sender ! RequestComplete }

I Besser?

(otherActor ? Request) map { case Response state += 1; RequestComplete

} pipeTo sender

I So geht’s!

(otherActor ? Request) map { case Response self ! IncState

RequestComplete } pipeTo sender

(17)

(Anti-)Patterns: State-Leaks

I Lokaler Zustand darf auf keinen Fall “auslaufen”!

var state = 0

(otherActor ? Request) map { case Response sender ! RequestComplete }

I Besser?

(otherActor ? Request) map { case Response state += 1; RequestComplete

} pipeTo sender

I So geht’s!

(otherActor ? Request) map { case Response self ! IncState

RequestComplete } pipeTo sender

(18)

(Anti-)Patterns: State-Leaks

I Lokaler Zustand darf auf keinen Fall “auslaufen”!

var state = 0

(otherActor ? Request) map { case Response sender ! RequestComplete }

I Besser?

(otherActor ? Request) map { case Response state += 1; RequestComplete

} pipeTo sender

I So geht’s!

(otherActor ? Request) map { case Response self ! IncState

RequestComplete } pipeTo sender

(19)

(Anti-)Patterns: Single-Responsibility

I Problem: Fehler in Komplexen Aktoren sind kaum behandelbar var interestDivisor = initial

def receive = {

case Divide(dividend, divisor) sender ! Quotient(dividend / divisor) case CalculateInterest(amount)

sender ! Interest(amount / interestDivisor) case AlterInterest(by)

interestDivisor += by }

I Welche Strategie beiDivByZeroException?

(20)

(Anti-)Patterns: Single-Responsibility

I Problem: Fehler in Komplexen Aktoren sind kaum behandelbar var interestDivisor = initial

def receive = {

case Divide(dividend, divisor) sender ! Quotient(dividend / divisor) case CalculateInterest(amount)

sender ! Interest(amount / interestDivisor) case AlterInterest(by)

interestDivisor += by }

I Welche Strategie beiDivByZeroException?

(21)

(Anti-)Patterns: Aktor-Beziehungen

M

S1 S2

I Problem: Wer registriert sich bei wem in einer Master-Slave-Hierarchie?

I Slaves sollten sich beim Master registrieren!

I Flexibel / Dynamisch

I Einfachere Konfiguration in verteilten Systemen

(22)

(Anti-)Patterns: Aktor-Beziehungen

M

S1

init -

S2

init

I Problem: Wer registriert sich bei wem in einer Master-Slave-Hierarchie?

I Slaves sollten sich beim Master registrieren!

I Flexibel / Dynamisch

I Einfachere Konfiguration in verteilten Systemen

(23)

Patterns: ...

I “Gefährliche Aufgaben” Kindern übertragen!

I Lange Aufgaben unterteilen

I Aktor Systeme sparsam erstellen

I Futures sparsam einsetzen

I Await.result()nurbei Interaktion mit Nicht-Aktor-Code

I Dokumentation Lesen!

(24)

Prozessalgebren und Modelchecking

I Prozessalgebren und temporale Logik beschreibenSysteme anhand ihrerZustandsübergänge

I Ein System ist dabei im wesentlichen eineendliche Zustandsmaschine M=hS,Σ,→imit Zustandsübergang → ⊆S×Σ×S

I Prozessalgebren erlaubenmehrere Zustandsmaschinen und ihre Synchronisation

I Damit modellieren wirnebenläufige Systeme

I ZurSpezifikation(CSP) aber auch alsBerechnungsmodell (π-Kalkül)

I Der Trick istAbstraktion: mehrere interne Zustandsübergänge werden zu einem Zustandsübergang zusammengefaßt

(25)

Beispiel: ein Flugbuchungssystem

I Operationen des Servers:

I Nimmt Anfragen an, schickt Resultate (mit flid)

I Nimmt Buchungsanfragen an, schickt Bestätigung (ok) oder Fehler (fail)

I Nimmt Stornierung an, schickt Bestätigung

I Unterscheidung zwischeninternerAuswahl u(Server trifft Entscheidung) undexternerAuswahl (Server reagiert) SERVER= query?(from,to)result!flid →SERVER

booking?flid →(ok →SERVER ufailSERVER) cancel?flid →okSERVER

(26)

Beispiel: ein Flugbuchungssystem

I Der Client:

I Stellt Anfrage

I wenn der Flug richtig ist, wird er gebucht;

I oder es wird eine neue Anfrage gestellt.

CLIENT =query!(from,to)result?flid →

(booking!flid → okCLIENT uCLIENT)

I Das Gesamtsystem — Client und Serversynchronisiert:

SYSTEM =CLIENT kSERVER

I Problem:Deadlock

I Es gibtWerkzeuge(Modelchecker, z.B. FDR), um solche Deadlocks in Spezifikationen zu finden

(27)

Beispiel: ein Flugbuchungssystem

I Der Client:

I Stellt Anfrage

I wenn der Flug richtig ist, wird er gebucht;

I oder es wird eine neue Anfrage gestellt.

CLIENT =query!(from,to)result?flid →

(booking!flid → okCLIENT uCLIENT)

I Das Gesamtsystem — Client und Serversynchronisiert:

SYSTEM =CLIENT kSERVER

I Problem:Deadlock

I Es gibtWerkzeuge(Modelchecker, z.B. FDR), um solche Deadlocks in Spezifikationen zu finden

(28)

Beispiel: ein Flugbuchungssystem

I Der Client:

I Stellt Anfrage

I wenn der Flug richtig ist, wird er gebucht;

I oder es wird eine neue Anfrage gestellt.

CLIENT =query!(from,to)result?flid

(booking!flid → (ok →CLIENT failCLIENT) uCLIENT)

I Das Gesamtsystem — Client und Serversynchronisiert:

SYSTEM =CLIENT kSERVER

I Problem:Deadlock

I Es gibtWerkzeuge(Modelchecker, z.B. FDR), um solche Deadlocks in Spezifikationen zu finden

Referenzen

ÄHNLICHE DOKUMENTE

I Santa wartet und koordiniert, sobald genügend “Teilnehmer” vorhanden I Elfen und Rentiere tun fortwährend dasselbe: Sammeln,

I Wenn längere Zeit keine Änderungen stattgefunden haben befinden sich schließlich alle Knoten im gleichen Zustand. I Wenn zwei Knoten die gleiche Menge Updates beobachten befinden

I Problem: Wir haben eine elastische, reaktive Anwendung aber nicht genug Geld um eine unbegrenzt große Server Farm zu betreiben. I Lösung: Bei Überlastung sollten Anfragen nicht

I Reaktive Programmierung kann diese Fehlerquellen einhegen I Theoretische Grundlagen zur Modellierung nebenläufiger Systeme. I zur

I Dynamische Tests führen das Programm unter kontrollierten Bedingungen aus, und prüfen das Ergebnis gegen eine gegebene Spezifikation. I Zentrale Frage: wo kommen die

I Systeme sind eingebettet, nebenläufig, reagieren auf ihre Umwelt.... Warum

I Aber: zentrales Konzept sind unendliche Listen (Ströme) mit nicht-strikte Auswertung. I Implementation mit Scala-Listen

I Promises sind das Gegenstück zu Futures trait Promise {. def complete(result: Try[T]) def