Markus Klink, @joheinz, markus.klink@oose.de

Reactive
Applications	
!

Scala, Play2 !
und Akka
All in one
Microservices
Kommunikation für REST
Schnittstellen!
viele kleine Systeme!
Technologiemix
Reactive Applications
http://reactivemanifesto.org

•

ereignisgetrieben!

•

skalierbar!

•

widerstandsfähig!

•

reakti...
Failures & Scalability
Hardware

Software

Network

DAU

•

Dinge scheitern!

•

Scaling: Je mehr Dinge wir haben, desto m...
Play
Framework

Fast
Redeployment

Zustandslos

JSON
Asynchron

Scala
& Java
Websockets

HTTP
Fallbeispiel: „Simple Mechanical Turk“
Server

Client

Client

Client

Master

Server

Server
Play
•

Asynchron, non blocking!

•

keine Abstraktion über HTTP Standard!

•

JSON friendly!

•

zustandslos!

•

Akka bu...
Fallbeispiel

!

•

3 Rollen: Client, Master, Server!

•

interne Kommunikation über Akteure!

•

externe Kommunikation üb...
Was ist ein Akteur?
Akteure kapseln Zustand, Verhalten, besitzen eine Mailbox
und bilden

Hierarchien.!

!

Akteure kommun...
Codebeispiel
class ImageActor(id: String, directoryActorRef: ActorRef) extends Actor {!
!
implicit val ec = context.dispat...
Akteur Hierarchien
Controller

reply

REST
Client

Controller

Master
RequestImage

REST

RequestImage

forward RequestIma...
Tell-Pattern
Sender

•

Empfänger ! SomeMessage!

•

„fire & forget“

Empfänger

// ImageServer	
def die(msg: String) = Act...
Ask-Pattern
Sender

•

Empfänger ? SomeMessage!

•

erwarte direkte Antwort vom Empfänger

Empfänger

// ImageMaster	
def ...
Forward
Sender

Intermediary

Empfänger

•

sender forward SomeMessage!

•

der ursprüngliche Sender wird „weitergereicht“
Router
Round Robin Router
Routee
!

!

Sender

Router

Routee

!

Routee

•

router ! SomeMessage!

•

sendet an einen ausgewählt...
Codebeispiel
class MasterActor(serverNames: List[String]) 	
extends Actor with ActorLogging with Configured {	

Bekommt de...
BroadCast Router
Routee

Sender

Router

Routee

Routee
!

•

router ! SomeMessage!

•

sendet einen Broadcast an alle Rou...
Codebeispiel
class MasterActor(serverNames: List[String]) 	
extends Actor with ActorLogging with Configured {	
!
…	
!
val ...
ScatterGather Router
Routee

Sender

Router

Routee

Routee

•

router ! SomeMessage!

•

sendet an alle Routees, und leit...
Codebeispiel
Erhält der MasterActor eine Evaluation (d.h. eine Liste vonTags für ein Bild),!
leitet er die Anfrage weiter ...
Circuit Breaker => Failure
Open

Closed

Halfopen

•

Circuit Breaker haben einen definierten Timeout und einen Retry Count...
Codebeispiel
Der Master verlangt vom ImageServer eine neue ImageId.!
!
!

/**	
Schlägt der Aufruf 3x fehl (maxFailures),
*...
Akteur Supervisor => Failure
!

Controller

reply

REST
Client

Master

Jeder Akteur hat einen zugewiesenen
Supervisor.!

...
Codebeispiel
// DirectoryActor receives Notification if it „died“ and the Supervisor handles the exception according	
// t...
Apache Camel
Framework zur Umsetzung von Enterprise Integration Patterns!

/**	
* Camel Producer endpoint which is configu...
Code
Upcoming SlideShare
Loading in...5
×

Reaktive Applikationen mit Scala, Play und Akka

2,289

Published on

Dieser Vortrag stellt mit Play2, Scala und Akka einen Technologiestack vor, der es ermöglicht relativ einfach eine skalierbare Webarchitektur aufzubauen, die mit dem Web und nicht gegen das Web arbeitet. Insbesondere der Einsatz von Akka als flexible Messagingplattform bietet dabei einige Vorteile gegenüber konventionellen Thread basierten Lösungen in Bezug auf die horizontale Skalierung der Applikation.

0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
2,289
On Slideshare
0
From Embeds
0
Number of Embeds
3
Actions
Shares
0
Downloads
10
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Reaktive Applikationen mit Scala, Play und Akka

  1. 1. Markus Klink, @joheinz, markus.klink@oose.de Reactive Applications ! Scala, Play2 ! und Akka
  2. 2. All in one
  3. 3. Microservices Kommunikation für REST Schnittstellen! viele kleine Systeme! Technologiemix
  4. 4. Reactive Applications http://reactivemanifesto.org • ereignisgetrieben! • skalierbar! • widerstandsfähig! • reaktionsschnell • HTML5/Javascript / Akteure! • zustandslos! • fehlerresistent / ausfallsicher
  5. 5. Failures & Scalability Hardware Software Network DAU • Dinge scheitern! • Scaling: Je mehr Dinge wir haben, desto mehr wird scheitern! • Scheitern muss in das System eingebaut sein => Resilient Systems ermöglichen es zu skalieren
  6. 6. Play Framework Fast Redeployment Zustandslos JSON Asynchron Scala & Java Websockets HTTP
  7. 7. Fallbeispiel: „Simple Mechanical Turk“ Server Client Client Client Master Server Server
  8. 8. Play • Asynchron, non blocking! • keine Abstraktion über HTTP Standard! • JSON friendly! • zustandslos! • Akka built in! • Websockets, Eventsource, Comet, …
  9. 9. Fallbeispiel ! • 3 Rollen: Client, Master, Server! • interne Kommunikation über Akteure! • externe Kommunikation über Akteure und Rest/Webservices
  10. 10. Was ist ein Akteur? Akteure kapseln Zustand, Verhalten, besitzen eine Mailbox und bilden Hierarchien.! ! Akteure kommunizieren über Nachrichten.! !
  11. 11. Codebeispiel class ImageActor(id: String, directoryActorRef: ActorRef) extends Actor {! ! implicit val ec = context.dispatcher! ! val ticker = context.system.scheduler.scheduleOnce(3.minutes, self, ImageActor.TimeOutImageEvaluation)! ! def receive = {! case ImageActor.Evaluation(_, tags) => ! ticker.cancel! log.info(s"received tags $tags for actor $self")! sender ! DirectoryActor.EvaluationAccepted! Nachrichten empfangen ! case ImageActor.TimeOutImageEvaluation =>! log.info("Image Expired, received time out")! log.info("sending parent a ExpiredImageEvaluation message")! directoryActorRef ! CommonMsg.ExpiredImageEvaluation(id)! }! } Nachrichten senden
  12. 12. Akteur Hierarchien Controller reply REST Client Controller Master RequestImage REST RequestImage forward RequestImage via Router Server ImageClient Server ImageMaster Response Directory create ImageActor Server Image Image ImageServer erzeugt Timer Image
  13. 13. Tell-Pattern Sender • Empfänger ! SomeMessage! • „fire & forget“ Empfänger // ImageServer def die(msg: String) = Action { directoryActor ! msg Ok }
  14. 14. Ask-Pattern Sender • Empfänger ? SomeMessage! • erwarte direkte Antwort vom Empfänger Empfänger // ImageMaster def image = Action.async { val responseFuture = (masterActor ? RequestImageId).mapTo[Response] responseFuture.map(response => response.status match { case 200 => Ok(response.body) case _ => BadRequest(response.body) }).recover { case connEx: Exception => (ServiceUnavailable(connEx.getMessage)) } }
  15. 15. Forward Sender Intermediary Empfänger • sender forward SomeMessage! • der ursprüngliche Sender wird „weitergereicht“
  16. 16. Router
  17. 17. Round Robin Router Routee ! ! Sender Router Routee ! Routee • router ! SomeMessage! • sendet an einen ausgewählten Routee! • Round Robin Router beinhaltet die Auswahllogik
  18. 18. Codebeispiel class MasterActor(serverNames: List[String]) extends Actor with ActorLogging with Configured { Bekommt der MasterActor eine Anfrage nach einer ImageId, ! sendet er die Anfrage an den RoundRobinRouter weiter. ! … val roundRobinRouter = context.actorOf(Props.empty.withRouter( RoundRobinRouter(routees = serverRoutees)), "RoundRobinRouter") Konfiguration ! def receive = LoggingReceive { case RequestImageId => roundRobinRouter forward RequestImageId case … => … } ! } Verwenden
  19. 19. BroadCast Router Routee Sender Router Routee Routee ! • router ! SomeMessage! • sendet einen Broadcast an alle Routees
  20. 20. Codebeispiel class MasterActor(serverNames: List[String]) extends Actor with ActorLogging with Configured { ! … ! val broadCastRouter = context.actorOf(Props.empty.withRouter( BroadcastRouter(routees = serverRoutees)), "BroadCastRouter") ! def receive = LoggingReceive { … ! case Ping => broadCastRouter forward Ping } ! } Der MasterActor fragt die einzelnen Server periodisch ab! und leitet Ping Anfragen an alle Server weiter. Konfiguration Verwenden
  21. 21. ScatterGather Router Routee Sender Router Routee Routee • router ! SomeMessage! • sendet an alle Routees, und leitet die erste Antwort zurück.
  22. 22. Codebeispiel Erhält der MasterActor eine Evaluation (d.h. eine Liste vonTags für ein Bild),! leitet er die Anfrage weiter ! class MasterActor(serverNames: List[String]) und bekommt eine Antwort vom ersten Server, ! extends Actor with ActorLogging with Configured { ! der sich dafür zuständig erklärt. … val scatterGatherRouter = context.actorOf(Props.empty.withRouter( ScatterGatherFirstCompletedRouter(routees = serverRoutees, within = appConfig.defaultTimeout)), "ScatterGatherRouter") Konfiguration ! case e: Evaluation => log.info(""" forwarding evaluation to scatterGatherRouter """) scatterGatherRouter forward e ! } ! } Verwenden
  23. 23. Circuit Breaker => Failure Open Closed Halfopen • Circuit Breaker haben einen definierten Timeout und einen Retry Counter! • Alles gut? => Closed state! • Timeout und Counter erreicht => Open State! • Open State und Request => probiere einen Request alle andere werden abgelehnt! • Half Open und Request => Alles Gut? => Closed sonst Open
  24. 24. Codebeispiel Der Master verlangt vom ImageServer eine neue ImageId.! ! ! /** Schlägt der Aufruf 3x fehl (maxFailures), * Represents a server serving images. werden weitere Aufrufe sofort mit Fehler zurückgemeldet, * */ bis sich der CirucitBreaker wieder schliesst. class ServerActor(url: String) extends Actor with ActorLogging { … val breaker = new CircuitBreaker(context.system.scheduler, Konfigurieren maxFailures = 3, callTimeout = 1 seconds, resetTimeout = 30 seconds) def receive = LoggingReceive { case RequestImageId => breaker.withCircuitBreaker(WS.url(imageUrl).get) pipeTo sender ! Verwenden case … } }
  25. 25. Akteur Supervisor => Failure ! Controller reply REST Client Master Jeder Akteur hat einen zugewiesenen Supervisor.! RequestImage • OneForOneStrategy: Supervisor behandelt den Fehler für den fehlgeschlagenen Akteur! • AllForOneStrategy: Supervisor behandelt den Fehler für alle „Siblings“ forward RequestImage Exception via Router Server Server Server
  26. 26. Codebeispiel // DirectoryActor receives Notification if it „died“ and the Supervisor handles the exception according // to the plan … override val supervisorStrategy = OneForOneStrategy(maxNrOfRetries = 10, withinTimeRange = 1 minute) { case _: UnsupportedOperationException Resume case _: FileNotFoundException case _: ActorKilledException case _: Exception Escalate } … Exceptions Restart Stop Konfiguration
  27. 27. Apache Camel Framework zur Umsetzung von Enterprise Integration Patterns! /** * Camel Producer endpoint which is configured via [[util.AppConfig.camelEndpoint]]. */ class CamelActor extends Actor with Producer with Oneway with Configured with ActorLogging{ ! lazy val appConfig = configured[AppConfig] def endpointUri = appConfig.camelEndpoint // e.g. "activemq:evaluations" ! } … // send Json as Inputstream to CamelActor val is = IOUtils.toInputStream(Json.prettyPrint(Json.toJson(eval))) val headerMap = Map(Exchange.FILE_NAME -> extractFileName(id)) camelActor ! CamelMessage(body = is, headers = headerMap) or „file://tmp/camel/…“
  28. 28. Code
  1. A particular slide catching your eye?

    Clipping is a handy way to collect important slides you want to go back to later.

×