Diese Präsentation wurde erfolgreich gemeldet.
Wir verwenden Ihre LinkedIn Profilangaben und Informationen zu Ihren Aktivitäten, um Anzeigen zu personalisieren und Ihnen relevantere Inhalte anzuzeigen. Sie können Ihre Anzeigeneinstellungen jederzeit ändern.

Backday Xebia : Akka, the reactive toolkit

973 Aufrufe

Veröffentlicht am

Plusieurs frameworks permettent de mettre en place facilement des microservices. Vert.x ou Sprint Cloud sont souvent cités. Venez découvrir comment Akka permet, grâce au modèle acteur, de construire des systèmes distribués complexes, résilient et scalable.

Nous verrons aussi les grands principes d'architecture à respecter pour tirer pleinement parti de cette technologie prometteuse.

Par Xavier Bucchiotthy et Fabian Guttierez

Veröffentlicht in: Technologie
  • Als Erste(r) kommentieren

Backday Xebia : Akka, the reactive toolkit

  1. 1. #backdaybyxebia FABIAN GUTIERREZ XAVIER BUCCHIOTTY Construire le SI de demain Akka, the reactive toolkit
  2. 2. #backdaybyxebia Speakers @FabGutierr @xbucchiotty
  3. 3. #backdaybyxebia Agenda ● Concepts ● Reactive Application ● Actor Basics ● Actor Supervision ● Scale OUT ● Use case
  4. 4. #backdaybyxebia Concepts
  5. 5. #backdaybyxebia Concurrency "Two or more tasks are making progress even though they might not be executing simultaneously" Parallelism "The execution of multiple things is truly simultaneous" Rob Pike - 'Concurrency Is Not Parallelism': https://vimeo.com/49718712
  6. 6. #backdaybyxebia Synchronous "A method call is considered synchronous if the caller cannot make progress until the method returns a value or exception" Asynchronous "Async call allows the caller to progress after a finite number of steps and the completion may be signaled via a callback, Future or message"
  7. 7. #backdaybyxebia Blocking "When the delay of one thread can indefinitely delay some of the other threads" Non blocking "No thread is able to indefinitely delay others"
  8. 8. #backdaybyxebia Reactive Application
  9. 9. #backdaybyxebia RUsers = REvents + RLoad + RFailure React to events, pushing rather than pulling React to load, focus on scalability rather than single-user performance React to failure, resilient systems with the ability to recover quickly at all levels
  10. 10. #backdaybyxebia
  11. 11. #backdaybyxebia - Áhkká All the wisdom and beauty of the world according to the sami mythology A mountain in Laponia in the north part of Sweden
  12. 12. #backdaybyxebia Problem It is very difficult to build: ● Correct highly concurrent systems ● Truly scalable systems ● Self-healing, fault- tolerant systems Goal Make simpler: ● Concurrency ● Scalability ● Fault-tolerance
  13. 13. #backdaybyxebia Scale UP is the same thing as Scale OUT -- Jonas Bonér
  14. 14. #backdaybyxebia Actor Basics
  15. 15. #backdaybyxebia A computational model that embodies: ● Processing ● Storage ● Communication Actor Model Carl Hewitt
  16. 16. #backdaybyxebia "The Actor model allows the developer to write concurrent and distributed systems by abstracting the low-level problems of having to deal with locking and thread management" Actor Model
  17. 17. #backdaybyxebia ● Lightweight objects ● Thread-safe ● Send and receive messages Actors
  18. 18. #backdaybyxebia ● Actors have a mailbox, all messages received go there ● When a message is received they decide what to do based on message type and content Actor Behaviour ● In addition to normal operations, they can create new actors or send messages to other actors ● Messages can only be sent to actors whose address is known
  19. 19. #backdaybyxebia Behaviour State Actor Event-driven Thread
  20. 20. #backdaybyxebia Defining Actors case object Tick class MyCounterActor extends Actor{ var counter = 0 def receive = { case Tick => counter += 1 println(counter) } } val config = ConfigFactory. load() val system = ActorSystem("system", config) val counterRef = system.actorOf( Props[MyCounterActor], "MyActor")
  21. 21. #backdaybyxebia Sending Messages to Actors counterRef ! Tick counterRef tell Tick counterRef.tell(Tick) counterRef.tell(Tick, senderRef) implicit val timeout = Timeout(5 seconds) val future = actor ? message //or val future = ask (actorRef, Tick, 5 seconds)
  22. 22. #backdaybyxebia Become / Unbecome class HotSwapActor extends Actor with Stash { import context._ def angry: Receive = { case "foo" => sender() ! "I am already angry?" case "bar" => become(happy) } def happy: Receive = { case "bar" => sender() ! "I am already happy :-)" case "foo" => become(angry) } def receive = { case "foo" => become(angry) case "bar" => become(happy) } } The Stash trait enables an actor to temporarily stash away messages that can not or should not be handled using the actor's current behavior
  23. 23. #backdaybyxebia Actor Paths and Addresses
  24. 24. #backdaybyxebia Actor Selection val actorRef = system.actorFor( "/MyActor/A") val parent = system.actorFor( "..") val sibling = system.actorFor( "../B") val refPath: ActorPath = actorRef.path val selection = system.actorSelection( "/MyActor/*") selection ! "hello there"
  25. 25. #backdaybyxebia Actor Supervision
  26. 26. #backdaybyxebia Supervision = Parenting
  27. 27. #backdaybyxebia The guardians
  28. 28. #backdaybyxebia The Guardians = Top level Supervisors /user, the guardian actor Parent of all user-created actors /system, the system guardian Allows an ordered shut-down sequence /, the root guardian Supervises all top level and special actors /user /system / You don’t interact with this other root actors as a user Root Actor
  29. 29. #backdaybyxebia ● When? the actor is in corrupt internal state Restarting ● How is it done? By creating a new instance of the actor and keeping the previous mailbox
  30. 30. #backdaybyxebia Lifecycle monitoring or DeathWatch ● An actor can monitor any other actor in order to react to his termination ● It means that supervision reacts to failure ● Each actor is the supervisor of its children, and as such each actor defines fault handling strategy
  31. 31. #backdaybyxebia Fault Tolerance(...or let it crash) When an actor fails… the supervisor will know what to do!!
  32. 32. #backdaybyxebia Default Supervision (in parent actors) final val defaultStrategy: SupervisorStrategy = { def defaultDecider: Decider = { case _: ActorInitializationException => Stop case _: ActorKilledException => Stop case _: Exception => Restart } OneForOneStrategy()(defaultDecider) } You don’t have to specify your own supervisor strategy in each and every actor. However, the default strategy looks like this:
  33. 33. #backdaybyxebia Defining a supervisor strategy class MyActorSupervisor extends Actor { override val supervisorStrategy = OneForOneStrategy ( maxNrOfRetries = 10, withinTimeRange = 1 minute) { case _: ArithmeticException => Resume case _: NullPointerException => Restart case _: IllegalArgumentException => Stop case _: Exception => Escalate } }
  34. 34. #backdaybyxebia No idea what to do? Ask your supervisor!! override val supervisorStrategy = OneForOneStrategy ( maxNrOfRetries = 10, withinTimeRange = 1 minute) { case _: ArithmeticException => Resume case t => super.supervisorStrategy.decider .applyOrElse(t,(_: Any) => Escalate) } One-For-One All-For-One OneForOneStrategy AllForOneStrategy Default strategy Recommended when there are tight dependencies among children Applies directives only to the failed child Applies directives to the failed child and siblings
  35. 35. #backdaybyxebia Manage Failure From Within class FaultTolerantService extends Actor { override def preRestart( reason: Throwable, message: Option[Any]) = { // clean up before restart } override def postRestart(reason: Throwable) = { // init after restart } ... } Lifecycle hooks: ● preStart ● postStop ● preRestart ● postRestart
  36. 36. #backdaybyxebia Scale UP
  37. 37. #backdaybyxebia Routing Redirects messages ● RoundRobin ● Random ● SmallestMailbox ● Broadcast ● custom val routerRef = system.actorOf (Props[Counter].withRouter( RoundRobinRouting( nrOfInstances = 5) )) akka.actor.deployment { /parent/router1 { router = round-robin- pool nr-of-instances = 5 } }
  38. 38. #backdaybyxebia Scale OUT
  39. 39. #backdaybyxebia
  40. 40. #backdaybyxebia Remote communication If no deployment configuration exist then the actor is deployed as local...it implies: ● Write as local ● Deploy as distributed in the cloud ● No code change
  41. 41. #backdaybyxebia Akka Remote Communication between systems is symmetric if a system A can connect to a system B then system B must also be able to connect to system A independently The role of the communicating systems are symmetric in regards to connection patterns There is no system that only accepts connections, and there is no system that only initiates connections
  42. 42. #backdaybyxebia akka { actor { provider = "akka.remote.RemoteActorRefProvider" } remote { enabled-transports = [ "akka.remote.netty.tcp"] netty.tcp { hostname = "127.0.0.1" port = 2552 } } } val selection = context.actorSelection( "akka.tcp://actorSystemName@10.0.0.1:2552/user/MyActor") selection ! "Pretty awesome feature"
  43. 43. #backdaybyxebia Akka Clustering ● Fault-tolerant ● Decentralized ● Peer-to-Peer Cluster membership service no single point of failure or single point of bottleneck
  44. 44. #backdaybyxebia Akka Clustering /producer/router { router = round-robin nr-of-instances = 100 cluster { enabled = on routees-path = "/user/routee" allow-local-routees = on } }
  45. 45. #backdaybyxebia Failure Detection ● Hashes the node ring ● Picks 5 nodes ● Request/Reply heartbeat Network Partition ● Failure detector can mark an unavailable member unreachable ● If one node is unreachable then no cluster convergence ● This means that the leader cannot perform its duties ● A member can become reachable again
  46. 46. #backdaybyxebia Testing Actors akka-testkit because JUnit is not enough
  47. 47. #backdaybyxebia Big Questions! ● Testing async calls without using threads explicitly ● You are not Brian Goetz and you want to use ThreadLocals ● CountDownLatch is not enough
  48. 48. #backdaybyxebia Enter Specs class MyEchoSpec(_system: ActorSystem) extends TestKit(_system) with ImplicitSender with WordSpecLike with Matchers with BeforeAndAfterAll { def this() = this(ActorSystem("MySpec")) override def afterAll { TestKit. shutdownActorSystem (system) } "An Echo actor" must { "send back messages unchanged" in { val echo = system.actorOf(TestActors.echoActorProps) echo ! "hello world" expectMsg("hello world") } } }
  49. 49. #backdaybyxebia Built-In Assertions expectMsg[T](d: Duration, msg: T): T expectNoMsg(d: Duration) expectMsgClass[T](d: Duration, c: Class[T]): T expectMsgType[T: Manifest](d: Duration) expectMsgAnyOf[T](d: Duration, obj: T*): T expectMsgAnyClassOf[T](d: Duration, obj: Class[_ <: T]*): T expectMsgAllOf[T](d: Duration, obj: T*): Seq[T] receiveN(n: Int, d: Duration): Seq[AnyRef]
  50. 50. #backdaybyxebia Multi-JVM "form a cluster" in { runOn(ClusterNodes: _*) { SeedDiscovery.joinCluster(system) enterBarrier( "deployed") } } "support network partition" in { runOn(node1) { for { from <- group_1 to <- group_2 } { testConductor. blackhole(from, to, Direction.Both).await } } }
  51. 51. #backdaybyxebia
  52. 52. #backdaybyxebia Use case
  53. 53. #backdaybyxebia
  54. 54. #backdaybyxebia TCP Server DB Actors are similar to objects.
  55. 55. #backdaybyxebia Actors process one message at a time. is injected in usesTCP Server DB
  56. 56. #backdaybyxebia TCP Server DB session 2 session 1 create create is injected in uses Actors can create other actors and supervise them.
  57. 57. #backdaybyxebia TCP Server DB session 2 session 1 create create is injected in uses Actors process one message at a time.
  58. 58. #backdaybyxebia TCP Server DB router session 2 session 1 create is injected in Actors can be behind routers to scale UP. conn 1 conn 2 create uses
  59. 59. #backdaybyxebia TCP Server DB router session 2 session 1 create is injected in conn 1 conn 2 create uses Actors can create other actors and supervise them.
  60. 60. #backdaybyxebia TCP Server DB router session 2 session 1 create is injected in conn 1 conn 2 create uses Actors can communicate with other actors. Alerting is injected in
  61. 61. #backdaybyxebia TCP Server DB router session 2 session 1 create is injected in conn 1 conn 2 create uses Actors can be deployed remotely to scale OUT. Alerting is injected in
  62. 62. #backdaybyxebia Alerting TCP Server DB router session 2 session 1 create is injected in conn 1 conn 2 create uses Actors can be deployed remotely to scale OUT. Alerting are injected in
  63. 63. #backdaybyxebia Questions?

×