Reactive Programming With Akka - Lessons Learned

A presentation at 33rd Degree 2014 in June 2014 in Kraków, Poland by Daniel Sawano

Slide 1

Slide 1

Platinum Sponsor REACTIVE(PROGRAMMING ( WITH(AKKA ( 1(LESSONS(LEARNED(1 Daniel Deogun & Daniel Sawano Twitter: @DanielDeogun, @DanielSawano

Slide 2

Slide 2

Who We Are DanielDeogun DanielSawano Omegapoint Stockholm-Gothenburg-Malmoe-Umea-NewYork

Slide 3

Slide 3

Agenda - Akkainanutshell  - Akka&Java  - AkkaandJava8Lambdas  - Domaininfluences  - Lessonslearnedfrombuildingrealsystems with Akka

Slide 4

Slide 4

Akka in a Nutshell http://akka.io/

Slide 5

Slide 5

Akka in a Nutshell Actors [1] By Dickelbers (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

! http://upload.wikimedia.org/wikipedia/commons/0/09/Sweden_postbox.JPG Messages Mailbox [1] ActorSystem Routers

Slide 6

Slide 6

Akka in a Nutshell Actors [1] By Dickelbers (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

! http://upload.wikimedia.org/wikipedia/commons/0/09/Sweden_postbox.JPG Messages Mailbox [1] ActorSystem Routers

Slide 7

Slide 7

Akka in a Nutshell Actors [1] By Dickelbers (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

! http://upload.wikimedia.org/wikipedia/commons/0/09/Sweden_postbox.JPG Messages Mailbox [1] ActorSystem Routers

Slide 8

Slide 8

Akka in a Nutshell Actors [1] By Dickelbers (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

! http://upload.wikimedia.org/wikipedia/commons/0/09/Sweden_postbox.JPG Messages Mailbox [1] ActorSystem Routers

Slide 9

Slide 9

Akka in a Nutshell Actors [1] By Dickelbers (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

! http://upload.wikimedia.org/wikipedia/commons/0/09/Sweden_postbox.JPG Messages Mailbox [1] ActorSystem Routers

Slide 10

Slide 10

Akka in a Nutshell Actors [1] By Dickelbers (Own work) [CC-BY-SA-3.0 (http://creativecommons.org/licenses/by-sa/3.0)], via Wikimedia Commons

! http://upload.wikimedia.org/wikipedia/commons/0/09/Sweden_postbox.JPG Messages Mailbox [1] ActorSystem Routers

Slide 11

Slide 11

Our definition of Legacy Code Legacy
ˈ le-g ə -s ē \

“: something that happened in the past or that comes from someone in the past ” !

  • Merriam-Webster

Slide 12

Slide 12

Our definition of Legacy Code Legacy
ˈ le-g ə -s ē \

“: something that happened in the past or that comes from someone in the past ” !

  • Merriam-Webster
  • Deogun-Sawano Legacy Code
    ˈ le-g ə -s ē
    ˈ k ō d\

“: code that does not satisfy the characteristics of a reactive system ”

Slide 13

Slide 13

What is Legacy Code? Characteristicsofareactivesystem,asdefinedbythereactive manifesto: -responsive -scalable -resilient -event-driven reactivemanifesto.org

Slide 14

Slide 14

Java or Scala IwanttobuildanapplicationwithAkka,shouldIuse JavaorScala? Well,itdepends... [1] https://duke.kenai.com/wave/.Midsize/Wave.png.png ! [2] http://www.scala-lang.org/ [1] [2]

Slide 15

Slide 15

Slide 16

Slide 16

Java or Scala Pros & Cons AssumewewanttobuildamachineMtosolvea problemPwhere,  Efficiencyisimperative  Sequentialcomputationsshallbeindependent ImplementationofMshallbeplatformindependent Complexityandboilerplatecodeshallbe reduced M’sbehaviorshallbeverifiable TimetoMarketisessentialandrisksshallbe minimized Scoreboard Java: Scala:

Slide 17

Slide 17

Java or Scala Pros & Cons AssumewewanttobuildamachineMtosolvea problemPwhere,  Efficiencyisimperative  Sequentialcomputationsshallbeindependent ImplementationofMshallbeplatformindependent Complexityandboilerplatecodeshallbe reduced M’sbehaviorshallbeverifiable TimetoMarketisessentialandrisksshallbe minimized Scoreboard Java: Scala: I I

X

Slide 18

Slide 18

Java or Scala Pros & Cons AssumewewanttobuildamachineMtosolvea problemPwhere,  Efficiencyisimperative  Sequentialcomputationsshallbeindependent ImplementationofMshallbeplatformindependent Complexityandboilerplatecodeshallbe reduced M’sbehaviorshallbeverifiable TimetoMarketisessentialandrisksshallbe minimized Scoreboard Java: Scala: I I I I

X X

Slide 19

Slide 19

Java or Scala Pros & Cons AssumewewanttobuildamachineMtosolvea problemPwhere,  Efficiencyisimperative  Sequentialcomputationsshallbeindependent ImplementationofMshallbeplatformindependent Complexityandboilerplatecodeshallbe reduced M’sbehaviorshallbeverifiable TimetoMarketisessentialandrisksshallbe minimized Scoreboard Java: Scala: I I I I I I

X X X

Slide 20

Slide 20

Java or Scala Pros & Cons AssumewewanttobuildamachineMtosolvea problemPwhere,  Efficiencyisimperative  Sequentialcomputationsshallbeindependent ImplementationofMshallbeplatformindependent Complexityandboilerplatecodeshallbe reduced M’sbehaviorshallbeverifiable TimetoMarketisessentialandrisksshallbe minimized Scoreboard Java: Scala: I I I I I I I

X X X X

Slide 21

Slide 21

Java or Scala Pros & Cons AssumewewanttobuildamachineMtosolvea problemPwhere,  Efficiencyisimperative  Sequentialcomputationsshallbeindependent ImplementationofMshallbeplatformindependent Complexityandboilerplatecodeshallbe reduced M’sbehaviorshallbeverifiable TimetoMarketisessentialandrisksshallbe minimized Scoreboard Java: Scala: I I I I I I I I

X X X X X

Slide 22

Slide 22

Java or Scala Pros & Cons AssumewewanttobuildamachineMtosolvea problemPwhere,  Efficiencyisimperative  Sequentialcomputationsshallbeindependent ImplementationofMshallbeplatformindependent Complexityandboilerplatecodeshallbe reduced M’sbehaviorshallbeverifiable TimetoMarketisessentialandrisksshallbe minimized Scoreboard Java: Scala: I I I I I I I I

X X X X X X

Slide 23

Slide 23

Slide 24

Slide 24

Akka All or nothing? Elastic Distributed Decentralized Resilient Akka Supervision Modularization Integration Parallelism Abstractionlevel

Slide 25

Slide 25

Akka All or nothing? Elastic Distributed Decentralized Resilient Akka Supervision Modularization Integration Parallelism Abstractionlevel

Slide 26

Slide 26

Akka All or nothing? Elastic Distributed Decentralized Resilient Akka Supervision Modularization Integration Parallelism Abstractionlevel

Slide 27

Slide 27

Akka All or nothing? Elastic Distributed Decentralized Resilient Akka Supervision Modularization Integration Parallelism Abstractionlevel

Slide 28

Slide 28

Akka All or nothing? Elastic Distributed Decentralized Resilient Akka Supervision Modularization Integration Parallelism Abstractionlevel

Slide 29

Slide 29

Akka All or nothing? Elastic Distributed Decentralized Resilient Akka Supervision Modularization Integration Parallelism Abstractionlevel

Slide 30

Slide 30

Slide 31

Slide 31

Slide 32

Slide 32

Reactive in a Legacy Environment? Blocking Blocking Blocking Blocking A B C D IsitpossibletoreplaceDbyacomponentimplementedwithAkka?

Slide 33

Slide 33

Debugger
Friend or Foe? Weoftengetthequestion: !  “TheasynchronyinAkkamakesitveryhardto usethedebugger,AmIdoingitwrong?”

Slide 34

Slide 34

debugger in
Legacy Design LegacyDesign ObjectA ObjectB ObjectN

Slide 35

Slide 35

debugger in
Legacy Design LegacyDesign ObjectA ObjectB

Slide 36

Slide 36

debugger in
Legacy Design LegacyDesign ObjectA ObjectB ObjectN PlaceabreakpointinNtofindout  -Whichvaluecausedthecrash?  -Whocreatedit?

Slide 37

Slide 37

debugger in

Reactive Design Reactivedesign BreakpointinactorN

Slide 38

Slide 38

Supervision We’rereactive

Slide 39

Slide 39

Supervision ohno I’mblocked butI’mstill pretty

We’rereactive

Slide 40

Slide 40

Supervision Asynchronous

Slide 41

Slide 41

Supervision Asynchronous Failure

Slide 42

Slide 42

Supervision Synchronous Blockingcall

Slide 43

Slide 43

Supervision Synchronous Blockingcall

Slide 44

Slide 44

Supervision Synchronous Blockingcall Sendfailure

Slide 45

Slide 45

Supervision Synchronous Blockingcall Sendfailure

Slide 46

Slide 46

Supervision ! private ActorRef targetActor; ! private ActorRef caller; ! private Timeout timeout; ! private Cancellable timeoutMessage; ! ! @Override ! public SupervisorStrategy supervisorStrategy() { ! return new OneForOneStrategy(0, Duration.Zero(), new Function<Throwable, SupervisorStrategy.Directive>() { ! public SupervisorStrategy.Directive apply(Throwable cause) { ! caller.tell(new Failure(cause), self()); ! return SupervisorStrategy.stop(); ! } ! }); ! } ! ! @Override ! public void onReceive(final Object message) throws Exception { ! if (message instanceof AskParam) { ! AskParam askParam = (AskParam) message; ! timeout = askParam.timeout; ! caller = sender(); ! targetActor = context().actorOf(askParam.props); ! context().watch(targetActor); ! targetActor.forward(askParam.message, context()); ! final Scheduler scheduler = context().system().scheduler(); ! timeoutMessage = scheduler.scheduleOnce(askParam.timeout.duration(), self(), new AskTimeout(), context().dispatcher(), null); ! } ! else if (message instanceof Terminated) { ! sendFailureToCaller(new ActorKilledException("Target actor terminated.")); ! timeoutMessage.cancel(); ! context().stop(self()); ! } ! else if (message instanceof AskTimeout) { ! sendFailureToCaller(new TimeoutException("Target actor timed out after " + timeout.toString())); ! context().stop(self()); ! } ! else { ! unhandled(message); ! } ! } ! ! private void sendFailureToCaller(final Throwable t) { ! caller.tell(new Failure(t), self()); ! }

Slide 47

Slide 47

Supervision - Writelegacycode - UseAkkaactors

Slide 48

Slide 48

Supervision - Writelegacycode - UseAkkaactors Sequentialdoesnotimplysynchronicity

Slide 49

Slide 49

Changing mindset Sequentialdoesnotimply  synchronicity

Slide 50

Slide 50

Changing mindset Sequentialdoesnotimply  synchronicity

Slide 51

Slide 51

Changing mindset Sequentialdoesnotimply  synchronicity

Slide 52

Slide 52

Changing mindset Sequentialdoesnotimply  synchronicity

Slide 53

Slide 53

Loose Coupling? Messages

Slide 54

Slide 54

The Shared Mutable State Trap Keepingstatebetweenmessagesinanactorisextremely dangerousbecauseitmaycauseasharedmutablestate ! ! !

Slide 55

Slide 55

The Shared Mutable State Trap Actor Properties -Onemessagequeue -Onlyonemessageisprocessedatatime -Messagesareprocessedinorderreceived -Anactormaychoosetodivideandconquer ataskbycalling otheractors

Slide 56

Slide 56

The Shared Mutable State Trap Router Actorsmaybegroupedinarouter Properties -Messagesaredistributedamongactors accordingtosomemessagedeliveryscheme,eg RoundRobinorSmallestMailbox ! -Aroutermayreceivealotofmessages

Slide 57

Slide 57

The Shared Mutable State Trap -Astatefulactoris partofa router ! -Ituses divideandconquertosolve itstask Actorwith state Scenario

Slide 58

Slide 58

The Shared Mutable State Trap Actorwith state -Eachmessagerecivedfromthe routerresets thestate ! -Newmessagesare intermixedwith childresponses ! -Hence,wehaveasharedmutable state  Scenario

Slide 59

Slide 59

The Shared Mutable State Trap Solution -Eachrequestsentbytherouter resultsina“Gather”actor ! -TheGatheractorisresponsible forcollectingtheresult ! -AGatheractorisNEVERreused Gatheractor result

Slide 60

Slide 60

Key Take-Aways -It’sveryeasytoaccidentallyfallbacktosequential“thinking” withstate  ! -Oftenonedoesnotrealizethisuntilthesystemisplaced underheavyload  ! -Trytoavoidstate!

Slide 61

Slide 61

Readability ByVarious.Editedby:WHMawandJDredge(Abandonedlibraryclearance.Selfphotographed.)[Publicdomain],viaWikimediaCommons

Slide 62

Slide 62

Implications of  untyped actors ! Akkaactorsareuntyped-bydesign ! ! public void onReceive(Object message)

Slide 63

Slide 63

Implications of  untyped actors ! Akkaactorsareuntyped-bydesign - Readability - Nosupportfrom compiler/IDE ! ! public void onReceive(Object message)

Slide 64

Slide 64

Message Handling V 1.0 ! ! @Override ! public void onReceive(Object message) { ! if (message instanceof SomeMessage) { ! doStuff(); ! } ! else { ! unhandled(message); ! } ! } !

Slide 65

Slide 65

V 1.0 - If-else contd. ! ! @Override ! public void onReceive(Object message) { ! if (message instanceof SomeMessage) { ! doStuff(); ! } ! else if (message instanceof SomeOtherMessage) { ! doSomeOtherStuff(); ! } ! else { ! unhandled(message); ! } ! } !

Slide 66

Slide 66

V 1.0 - If-else mess ! ! @Override ! public void onReceive(Object message) { ! if (message instanceof SomeMessage) { ! doStuff(); ! } ! else if (message instanceof SomeOtherMessage) { ! doSomeOtherStuff(); ! } ! else if (message instanceof YetAnother Message) { ! doEvenMore Stuff(); ! } ! else { ! unhandled(message); ! } ! } !

Slide 67

Slide 67

Evolution of message handling ! ! ! ! @Override ! public void onReceive(Object message) { ! ... ! } ! ! http://upload.wikimedia.org/wikipedia/commons/thumb/6/69/Human_evolution.svg/2000px-Human_evolution.svg.png

Slide 68

Slide 68

V 2.0 - Overloading ! public void onMessage(SomeMessage message) {...} ! ! public void onMessage(SomeOtherMessage message) {...}

Slide 69

Slide 69

V 2.0 - Overloading ! public void onMessage(SomeMessage message) {...} ! ! public void onMessage(SomeOtherMessage message) {...} ! @Override ! public void onReceive(Object message) { ! ... ! ! methods.get(message.getClass()).invoke(this, message); ! ! ... ! } !

Slide 70

Slide 70

V 2.1 - Annotations ! ! class Worker extends BaseActor { !

!

@Response !

public void onMessage(SomeMessage message) {...} ! ! ! public void onMessage(SomeOtherMessage message) {...} ! }

Slide 71

Slide 71

V 3.0 - Contract ! ! ! interface Messages {
! ! void doSomething (SomeMessage message); ! ! void doSomethingElse (SomeOtherMessage message); ! ! } ! ! ! !

Slide 72

Slide 72

V 3.0 - Contract ! ! ! interface Messages {
! ! void doSomething (SomeMessage message); ! ! void doSomethingElse (SomeOtherMessage message); ! ! } ! ! ! ! ! SomeActor extends BaseActor implements Messages {...} !

Slide 73

Slide 73

V 3.0 - Contract ! ! class Worker extends BaseActor implements Messages { !

! ! public void handleResponse (SomeMessage message) {...} ! ! ! public void handleRequest(SomeOtherMessage message) {...} ! ! }

Slide 74

Slide 74

V 3.0 - Contract ! ! BaseActor extends UntypedActor { ! !

@Override ! ! public void preStart() { ! methodDelegate = new MethodDelegate(this); ! } ! ! @Override ! public void onReceive(Object message) { ! if (methodDelegate.onReceive(message)) { ! return; ! } ! unhandled(message); ! } ! } !

Slide 75

Slide 75

Before ! class Worker extends BaseActor implements Messages { !

@Override !

public void onReceive(Object message) { !

if (message instanceof SomeMessage) { !

doStuff(); !

}

!

else if (message instanceof SomeOtherMessage) { !

doSomeOtherStuff(); ! } ! else if (message instanceof YetAnother Message) { ! doEvenMore Stuff(); !

}

!

else { !

unhandled(message); !

}

!

Slide 76

Slide 76

After ! ! class Worker extends BaseActor implements Messages {
! ! public void handleResponse(SomeMessage message) { ! doStuff(); !

} ! ! public void handleRequest(SomeOtherMessage message) { ! doSomeOtherStuff(); ! } ! ! public void process(YetAnotherMessage message) { ! doEvenMoreStuff(); ! } ! } !

Slide 77

Slide 77

Akka & Java 8 Lambdas

  • Duke: https://duke.kenai.com/thumbsup/DukeWithHelmet.png !
  • Lambda: http://en.wikipedia.org/wiki/Lambda_calculus

Slide 78

Slide 78

Warning http://doc.akka.io/docs/akka/2.3.3/java/lambda-actors.html

Slide 79

Slide 79

The Receive Builder ! ! public class MyActor extends AbstractActor { ! public MyActor() { ! receive(ReceiveBuilder. ! match(SomeMessage.class, m -> { ! doStuff(); ! }). ! match(SomeOtherMessage.class, m -> { ! doSomeOtherStuff(); ! }). ! match(YetAnotherMessage.class, m -> { ! yetSomeMoreStuff(); ! }). ! matchAny(this::unhandled). ! build()); ! } ! } !

Slide 80

Slide 80

A Quick Note On Performance - ThepartialfunctionscreatedbytheReceiveBuilder consistofmultiplelambdaexpressionsforevery matchstatement whichmaybehardfortheJVMto optimize ! - Theresultingcodemaynotbeasperformantasthe correspondinguntypedactorversion

Slide 81

Slide 81

Conclusions - Contractstoexplicitlydefinebehaviorworks prettywell - Canbeausefultoolinyourtoolbox - Java8andlambdasprovidesadditionalapproaches - Scalacangivesimilarsupportviatraits&match

Slide 82

Slide 82

Testing Akka Code Interactbysending messages BDD Scenarios Integrationtests

Slide 83

Slide 83

Scenarios CaseA1: Sortanysequenceofnumbersinincreasingorder ! ! Given  asequenceofnumbersindecreasingorder ! When applyingthesortalgorithm  ! Then theresultingsequenceofnumbersisinincreasingorder

Slide 84

Slide 84

The Test ! ! ! ! @Test ! public void case A1() { ! ! given(sequence(9,8,7,6,5,4,3,2,1,0)) ; !

! whenSorting (); !

! thenResultIs(sequence(0,1,2,3,4,5,6,7,8,9) ); ! ! } !

Slide 85

Slide 85

Key Take-Aways - It’spossibletouseAkkainlegacycode - AkkaisScala&Javacompliant - Akkaisatoolkitwithalotofgoodies - Stopwritinglegacycode

Slide 86

Slide 86

Thankyou @DanielDeogun@DanielSawano