SlideShare a Scribd company logo
1 of 71
Download to read offline
Effective	
  Actors
                             Jamie	
  Allen




Saturday, March 2, 13
Who	
  Am	
  I?

         •Consultant	
  at	
  Typesafe
         •Actor	
  &	
  Scala	
  developer	
  since	
  2009

                        jamie.allen@typesafe.com


                                                              @jamie_allen

Typesafe 社でコンサルタントしています
Saturday, March 2, 13
Effective	
  Actors

         •Best	
  practices	
  based	
  on	
  several	
  years	
  of	
  actor	
  
                development
         •Helpful	
  hints	
  for	
  reasoning	
  about	
  actors	
  at	
  runtime



                                                                            @jamie_allen

何年かの開発に基づいたベスト・プラクティスとヒント
Saturday, March 2, 13
Actors
            •Concurrent,	
                                 A
                    lightweight	
  
                    processes	
  that	
  
                    communicate	
                      B       C

                    through	
  
                    asynchronous	
                         D
                    message	
  passing

            •Isolation	
  of	
  state,	
  no	
     E       F         G
                    internal	
  concurrency
非同期なメッセージを用いて対話する並行プロセス                                        @jamie_allen

状態の隔離
Saturday, March 2, 13
Akka	
  Actors
        class Pinger extends Actor {
          def receive = {
            case "Pong" => println("Pinging!"); sender ! "Ping!"
          }
        }

        class Ponger extends Actor {
          def receive = {
            case "Ping" => println("Ponging!"); sender ! "Pong!"
          }
        }

        object PingPong extends App {
          val system = ActorSystem()
          val pinger = system.actorOf(Props[Pinger])
          val ponger = system.actorOf(Props[Ponger])
          pinger.tell("Pong!", ponger)
          Thread.sleep(1000)
          system.shutdown
        }


                                                                   @jamie_allen


Saturday, March 2, 13
Akka	
  Actors
        class Pinger extends Actor {
          def receive = {
            case "Pong" => println("Pinging!"); sender ! "Ping!"
          }
        }

        class Ponger extends Actor {
          def receive = {
            case "Ping" => println("Ponging!"); sender ! "Pong!"
          }
        }

        object PingPong extends App {
          val system = ActorSystem()
          val pinger = system.actorOf(Props[Pinger])
          val ponger = system.actorOf(Props[Ponger])
          pinger.tell("Pong!", ponger)
          Thread.sleep(1000)
          system.shutdown
        }


                                                                   @jamie_allen


Saturday, March 2, 13
Akka	
  Actors
        class Pinger extends Actor {
          def receive = {
            case "Pong" => println("Pinging!"); sender ! "Ping!"
          }
        }

        class Ponger extends Actor {
          def receive = {
            case "Ping" => println("Ponging!"); sender ! "Pong!"
          }
        }

        object PingPong extends App {
          val system = ActorSystem()
          val pinger = system.actorOf(Props[Pinger])
          val ponger = system.actorOf(Props[Ponger])
          pinger.tell("Pong!", ponger)
          Thread.sleep(1000)
          system.shutdown
        }


                                                                   @jamie_allen


Saturday, March 2, 13
Akka	
  Actors
        class Pinger extends Actor {
          def receive = {
            case "Pong" => println("Pinging!"); sender ! "Ping!"
          }
        }

        class Ponger extends Actor {
          def receive = {
            case "Ping" => println("Ponging!"); sender ! "Pong!"
          }
        }

        object PingPong extends App {
          val system = ActorSystem()
          val pinger = system.actorOf(Props[Pinger])
          val ponger = system.actorOf(Props[Ponger])
          pinger.tell("Pong!", ponger)
          Thread.sleep(1000)
          system.shutdown
        }
                           Overriding the “sender”
                                                                   @jamie_allen


Saturday, March 2, 13
Supervisor	
  Hierarchies
                                                            A



            •Specifies	
  handling	
                     B       C
                    mechanisms	
  for	
  
                    groupings	
  of	
  actors	
  
                    in	
  parent/child	
                    D

                    relationship
                                                    E       F         G



                                                                @jamie_allen

Supervisor はアクター階層の処理を定義する
Saturday, March 2, 13
Akka	
  Supervisors

        class MySupervisor extends Actor {
          override val supervisorStrategy =
            OneForOneStrategy() {
              case ae: ArithmeticException => Resume
              case np: NullPointerException => Restart
            }

            context.actorOf(Props[MyActor])
        }




                                                         @jamie_allen


Saturday, March 2, 13
Akka	
  Supervisors

        class MySupervisor extends Actor {
          override val supervisorStrategy =
            OneForOneStrategy() {
              case ae: ArithmeticException => Resume
              case np: NullPointerException => Restart
            }

            context.actorOf(Props[MyActor])
        }




                                                         @jamie_allen


Saturday, March 2, 13
Akka	
  Supervisors

        class MySupervisor extends Actor {
          override val supervisorStrategy =
            OneForOneStrategy() {
              case ae: ArithmeticException => Resume
              case np: NullPointerException => Restart
            }

            context.actorOf(Props[MyActor])
        }




            Note the “context”
                                                         @jamie_allen


Saturday, March 2, 13
Domain	
  Supervision

         •Each	
  supervisor	
  manages	
  a	
  grouping	
  of	
  types	
  in	
  
                a	
  domain

         •Actors	
  persist	
  to	
  represent	
  existence	
  of	
  
                instances	
  and	
  contain	
  their	
  own	
  state

         •Actors	
  constantly	
  resolve	
  the	
  world	
  as	
  it	
  should	
  
                be	
  against	
  the	
  world	
  as	
  it	
  is


                                                                        @jamie_allen

Supervisor 階層を利用しドメインをモデルする
Saturday, March 2, 13
Worker	
  Supervision
         •Supervisors	
  should	
  hold	
  all	
  critical	
  data
         •Workers	
  should	
  receive	
  data	
  for	
  tasks	
  in	
  
                messages

         •Workers	
  being	
  supervised	
  should	
  perform	
  
                dangerous	
  tasks

         •Supervisor	
  should	
  know	
  how	
  to	
  handle	
  failures	
  
                in	
  workers	
  in	
  order	
  to	
  retry	
  appropriately

Supervisor がデータを保持し、メッセージでワーカーに渡す
                             @jamie_allen

ワーカーは死んでも構わない
Saturday, March 2, 13
Parallelism
            •Easily	
  scale	
  a	
  task	
  by	
                A
                    creating	
  multiple	
  
                    instances	
  of	
  an	
  actor	
  
                    and	
  applying	
  work	
                B       C

                    using	
  various	
  
                    strategies                                   D


            •Order	
  is	
  not	
  
                    guaranteed,	
  nor	
                 E       F         G
                    should	
  it	
  be
                                                                     @jamie_allen

複数のアクターを作成することでタスクをスケール
Saturday, March 2, 13
Akka	
  Routing

        class MyActor extends Actor {
          def receive = { case x => println(x) }
        }

        object Parallelizer extends App {
          val system = ActorSystem()
          val router: ActorRef = system.actorOf(Props[MyActor].
            withRouter(RoundRobinRouter(nrOfInstances = 5)))

            for (i <- 1 to 10) router ! i
        }




                                                                  @jamie_allen


Saturday, March 2, 13
Akka	
  Routing

        class MyActor extends Actor {
          def receive = { case x => println(x) }
        }

        object Parallelizer extends App {
          val system = ActorSystem()
          val router: ActorRef = system.actorOf(Props[MyActor].
            withRouter(RoundRobinRouter(nrOfInstances = 5)))

            for (i <- 1 to 10) router ! i
        }




                                                                  @jamie_allen


Saturday, March 2, 13
Akka	
  Routing

        class MyActor extends Actor {
          def receive = { case x => println(x) }
        }

        object Parallelizer extends App {
          val system = ActorSystem()
          val router: ActorRef = system.actorOf(Props[MyActor].
            withRouter(RoundRobinRouter(nrOfInstances = 5)))

            for (i <- 1 to 10) router ! i
        }


                                    Should be configured externally

                                                                  @jamie_allen


Saturday, March 2, 13
Akka	
  Routing

        class MyActor extends Actor {
          def receive = { case x => println(x) }
        }

        object Parallelizer extends App {
          val system = ActorSystem()
          val router: ActorRef = system.actorOf(Props[MyActor].
            withRouter(RoundRobinRouter(nrOfInstances = 5)))

            for (i <- 1 to 10) router ! i
        }




                                                                  @jamie_allen


Saturday, March 2, 13
RULE:
              Actors Should Only Do One Thing



                                          @jamie_allen

アクターは1つの事に特化すること
Saturday, March 2, 13
Single	
  Responsibility	
  Principle

         •Do	
  not	
  conflate	
  responsibilities	
  in	
  actors
         •Becomes	
  hard	
  to	
  define	
  the	
  boundaries	
  of	
  
                responsibility

         •Supervision	
  becomes	
  more	
  difficult	
  as	
  you	
  
                handle	
  more	
  possibilities

         •Debugging	
  becomes	
  very	
  difficult
                                                                    @jamie_allen

単一責任の原則: なんでもかんでも手を出さない
Saturday, March 2, 13
Supervision


         •Every	
  non-­‐leaf	
  node	
  is	
  technically	
  a	
  supervisor
         •Create	
  explicit	
  supervisors	
  under	
  each	
  node	
  for	
  
                each	
  type	
  of	
  child	
  to	
  be	
  managed




                                                                     @jamie_allen

アクターの種類ごとに Supervisor を分けること
Saturday, March 2, 13
Conflated	
  Supervision

          C1                               C2                             Customers



                                                                         Accounts &
                          Ac1   Ac2        D1        D2        D3
                                                                          Devices




                                      A1        A2        A3        A4   Applications




                                                                         @jamie_allen

混ざってる Supervisor
Saturday, March 2, 13
Explicit	
  Supervision

                C1                              C2                                  Customers


                                                               DS                  Accounts &
                                AS
                                                                                    Devices




                        Ac1          Ac2             D1        D2        D3




                                           A1             A2        A3        A4   Applications
                                                                                   @jamie_allen

明示的な Supervisor
Saturday, March 2, 13
Keep	
  the	
  Error	
  Kernel	
  Simple

         •Limit	
  the	
  number	
  of	
  supervisors	
  you	
  create	
  at	
  
                this	
  level

         •Helps	
  with	
  fault	
  tolerance	
  and	
  explicit	
  handling	
  
                of	
  errors	
  through	
  the	
  hierarchy

         •Akka	
  uses	
  synchronous	
  messaging	
  to	
  create	
  
                top-­‐level	
  actors


                                                                       @jamie_allen

Error Kernel はシンプルに
Saturday, March 2, 13
Use	
  Failure	
  Zones

         •Multiple	
  isolated	
  zones	
  with	
  their	
  own	
  
                resources	
  (thread	
  pools,	
  etc)

         •Prevents	
  starvation	
  of	
  actors
         •Prevents	
  issues	
  in	
  one	
  branch	
  from	
  affecting	
  
                another


                                                                      @jamie_allen

Failure Zone を使ってリソースを隔離する
Saturday, March 2, 13
Failure	
  Zones

                C1                         C2                             Customers


                         AS                          DS                  Accounts &
                                                                          Devices




                   Ac1        Ac2          D1        D2        D3




                                      A1        A2        A3        A4   Applications
                                                                         @jamie_allen


Saturday, March 2, 13
Failure	
  Zones

                C1                         C2                             Customers


                         AS                          DS                  Accounts &
                                                                          Devices




                   Ac1        Ac2          D1        D2        D3




                                      A1        A2        A3        A4   Applications
                                                                         @jamie_allen


Saturday, March 2, 13
Takeaway

         •Isolation	
  of	
  groups	
  of	
  actors	
  limits	
  the	
  effects	
  
                of	
  failure

         •For	
  reasonably	
  complex	
  actor	
  systems,	
  shallow	
  
                trees	
  are	
  a	
  smell	
  test

         •Actors	
  are	
  cheap	
  -­‐	
  use	
  them

                                                                         @jamie_allen

アクターのグループを隔離することで障害の影響を抑える
Saturday, March 2, 13
RULE:
     Block Only When and Where You Must



                                  @jamie_allen

必要な時に、必要な場所のみでブロックすること
Saturday, March 2, 13
Consequences	
  of	
  Blocking


         •Eventually	
  results	
  in	
  actor	
  starvation	
  as	
  thread	
  
                pool	
  dries	
  up

         •Horrible	
  performance
         •Massive	
  waste	
  of	
  system	
  resources

ブロッキングの行く末: 無くなるスレッド、飢えるアクター、
                         @jamie_allen

落ちる性能
Saturday, March 2, 13
Futures
        class Worker extends Actor {
          def receive = {
            case s: Seq[Int] => sender ! s.reduce(_ + _)
          }
        }

        class Delegator extends Actor {
          implicit val timeout: Timeout = 2 seconds
          val worker = context.actorOf(Props[Worker])
          def receive = {
            case "Start" =>
              worker ? (1 to 100) map
                (x => println("Got value: %d".format(x)))
          }
        }

        object Bootstrapper extends App {
          val system = ActorSystem()
          val delegator = system.actorOf(Props[Delegator])
          delegator ! "Start"
          Thread.sleep(1000)
          system.shutdown
        }
                                                             @jamie_allen


Saturday, March 2, 13
Futures
        class Worker extends Actor {
          def receive = {
            case s: Seq[Int] => sender ! s.reduce(_ + _)
          }
        }

        class Delegator extends Actor {
          implicit val timeout: Timeout = 2 seconds
          val worker = context.actorOf(Props[Worker])
          def receive = {
            case "Start" =>
              worker ? (1 to 100) map
                (x => println("Got value: %d".format(x)))
          }
        }

        object Bootstrapper extends App {
          val system = ActorSystem()
          val delegator = system.actorOf(Props[Delegator])
          delegator ! "Start"
          Thread.sleep(1000)
          system.shutdown
        }
                                                             @jamie_allen


Saturday, March 2, 13
Futures
        class Worker extends Actor {
          def receive = {
            case s: Seq[Int] => sender ! s.reduce(_ + _)
          }
        }

        class Delegator extends Actor {
          implicit val timeout: Timeout = 2 seconds
          val worker = context.actorOf(Props[Worker])
          def receive = {
            case "Start" =>
              worker ? (1 to 100) map
                (x => println("Got value: %d".format(x)))
          }
        }

        object Bootstrapper extends App {
          val system = ActorSystem()
          val delegator = system.actorOf(Props[Delegator])
          delegator ! "Start"
          Thread.sleep(1000)
          system.shutdown
        }
                                                             @jamie_allen


Saturday, March 2, 13
Futures
        class Worker extends Actor {
          def receive = {
            case s: Seq[Int] => sender ! s.reduce(_ + _)
          }
        }

        class Delegator extends Actor {
          implicit val timeout: Timeout = 2 seconds
          val worker = context.actorOf(Props[Worker])
          def receive = {
            case "Start" =>
              worker ? (1 to 100) map
                (x => println("Got value: %d".format(x)))
          }
        }

        object Bootstrapper extends App {
          val system = ActorSystem()
          val delegator = system.actorOf(Props[Delegator])
          delegator ! "Start"
          Thread.sleep(1000)
          system.shutdown
        }
                                                             @jamie_allen


Saturday, March 2, 13
Futures
        class Worker extends Actor {
          def receive = {
            case s: Seq[Int] => sender ! s.reduce(_ + _)
          }
        }

        class Delegator extends Actor {
          implicit val timeout: Timeout = 2 seconds
          val worker = context.actorOf(Props[Worker])
          def receive = {
            case "Start" =>
              worker ? (1 to 100) map
                (x => println("Got value: %d".format(x)))
          }
        }

        object Bootstrapper extends App {
          val system = ActorSystem()
          val delegator = system.actorOf(Props[Delegator])
          delegator ! "Start"
          Thread.sleep(1000)
          system.shutdown
        }
                                                             @jamie_allen


Saturday, March 2, 13
Sequential	
  Futures


        val r: Future[Int] = for {
          a <- (service1 ? GetResult).mapTo[Int]
          b <- (service2 ? GetResult(a)).mapTo[Int]
        } yield a * b




                                                      @jamie_allen

順次 Future
Saturday, March 2, 13
Sequential	
  Futures

                                 Type Safety

        val r: Future[Int] = for {
          a <- (service1 ? GetResult).mapTo[Int]
          b <- (service2 ? GetResult(a)).mapTo[Int]
        } yield a * b




                                                      @jamie_allen

順次 Future
Saturday, March 2, 13
Parallel	
  Futures

        First way: Define futures first
        val f1: Future[Int] = service1 ? GetResult
        val f2: Future[Int] = service2 ? GetResult

        val r: Future[Int] = for {
          a <- f1
          b <- f2
        } yield a * b




                                                     @jamie_allen

並列 Future 方法1: 事前に Future を定義
Saturday, March 2, 13
Parallel	
  Futures


     Second way: Define in one line of for comprehension
      val r: Future[Int] = for {
        (a: Int, b: Int) <- (service1 ? GetResult) zip (service2 ? GetResult)
      } yield a * b




                                                   Note the “zip”


                                                                   @jamie_allen

並列 Future 方法2: zip を使って 1行で定義
Saturday, March 2, 13
Blocking
         •An	
  example	
  is	
  database	
  access
         •Use	
  a	
  specialized	
  actor	
  with	
  its	
  own	
  resources
         •Pass	
  messages	
  to	
  other	
  actors	
  to	
  handle	
  the	
  
                result

         •Scala	
  provides	
  “Managed	
  Blocking”	
  to	
  limit	
  the	
  
                number	
  of	
  blocking	
  operations	
  taking	
  place	
  in	
  
                actors	
  at	
  one	
  time

                                                                          @jamie_allen

ブロッキング専門のアクターを作る
Saturday, March 2, 13
Akka	
  Dispatcher
        class Worker extends Actor {
          def receive = {
            case s: Seq[Int] => sender ! s.reduce(_ + _)
          }
        }

        class Delegator extends Actor {
          implicit val timeout: Timeout = 2 seconds
          val worker = context.actorOf(Props[Worker]).
            withDispatcher(“my-dispatcher”)
                                                             Failure
          def receive = {
            case _ =>
                                                              Zone
              blocking {
                val futResult = worker ? (1 to 100)
                val result = Await.result(futResult, 2 seconds)
              }
          }
        }



                                                                  @jamie_allen


Saturday, March 2, 13
Push,	
  Not	
  Pull

         •Start	
  with	
  no	
  guarantees	
  about	
  delivery
         •Add	
  guarantees	
  only	
  where	
  you	
  need	
  them
         •Retry	
  until	
  you	
  get	
  the	
  answer	
  you	
  expect
         •Switch	
  your	
  actor	
  to	
  a	
  "nominal"	
  state	
  at	
  that	
  
                point


                                                                           @jamie_allen

配達時間はまず保証無しから始める
Saturday, March 2, 13
Takeaway


         •Find	
  ways	
  to	
  ensure	
  that	
  your	
  actors	
  remain	
  
                asynchronous	
  and	
  non-­‐blocking

         •Avoid	
  making	
  your	
  actors	
  wait	
  for	
  anything	
  
                while	
  handling	
  a	
  message



                                                                        @jamie_allen

アクターが非同期で非ブロッキングであるように努めること
Saturday, March 2, 13
RULE:
                        Do Not Optimize Prematurely



                                                  @jamie_allen

早すぎる最適化はダメ
Saturday, March 2, 13
Start	
  Simple


         •Make	
  Donald	
  Knuth	
  happy
         •Start	
  with	
  a	
  simple	
  configuration	
  and	
  profile
         •Do	
  not	
  parallelize	
  until	
  you	
  know	
  you	
  need	
  to	
  
                and	
  where



                                                                          @jamie_allen

プロファイルも取らずに並列化しないこと
Saturday, March 2, 13
Initial	
  Focus

         •Deterministic
         •Declarative
         •Immutable
         •Start	
  with	
  functional	
  programming	
  and	
  go	
  
                from	
  there


                                                                  @jamie_allen

まずは決定的、宣言型、不変など関数型の基本から
Saturday, March 2, 13
Advice	
  From	
  Jonas	
  Bonér

         •Layer	
  in	
  complexity
         •Add	
  indeterminism
         •Add	
  mutability	
  in	
  hot	
  spots	
  
                (CAS	
  and	
  STM)

         •Add	
  explicit	
  locking	
  and	
  
                threads	
  as	
  a	
  last	
  resort    Photo courtesy of Brian Clapper, NE Scala 2011




段階的に複雑さを導入する: 1. 非決定性 2. 可変性                                                  @jamie_allen

3. スレッドと明示的なロックは最終手段
Saturday, March 2, 13
Prepare	
  for	
  Race	
  Conditions

         •Write	
  actor	
  code	
  to	
  be	
  agnostic	
  of	
  time	
  and	
  
                order

         •Actors	
  should	
  only	
  care	
  about	
  now,	
  not	
  that	
  
                something	
  happened	
  before	
  it

         •Actors	
  can	
  "become"	
  or	
  represent	
  state	
  
                machines	
  to	
  represent	
  transitions


                                                                           @jamie_allen

アクターは時間と順序に無関心であるべき
Saturday, March 2, 13
Beware	
  the	
  Thundering	
  Herd
         •Actor	
  systems	
  can	
  be	
  overwhelmed	
  by	
  "storms"	
  of	
  
                messages	
  flying	
  about

         •Do	
  not	
  pass	
  generic	
  messages	
  that	
  apply	
  to	
  many	
  
                actors

         •Dampen	
  actor	
  messages	
  if	
  the	
  exact	
  same	
  message	
  is	
  
                being	
  handled	
  repeatedly	
  within	
  a	
  certain	
  timeframe

         •Tune	
  your	
  dispatchers	
  and	
  mailboxes	
  via	
  back-­‐off	
  
                policies	
  and	
  queue	
  sizes

         •Akka	
  now	
  has	
  Circuit	
  Breakers
メッセージの「嵐」に注意                                                                  @jamie_allen

複数のアクターに作用する汎用メッセージは避ける
Saturday, March 2, 13
Takeaway


         •Start	
  by	
  thinking	
  in	
  terms	
  of	
  an	
  implementation	
  
                that	
  is	
  deterministic	
  and	
  not	
  actor	
  based

         •Layer	
  in	
  complexity	
  as	
  you	
  go

                                                                              @jamie_allen

まずはアクターを使わない決定的な実装から
Saturday, March 2, 13
RULE:
                        Be Explicit In Your Intent



                                                     @jamie_allen

意図をハッキリさせること
Saturday, March 2, 13
Name	
  Your	
  Actors
         •Allows	
  for	
  external	
  configuration
         •Allows	
  for	
  lookup
         •Better	
  semantic	
  logging

            val system = ActorSystem("pingpong")
            val pinger = system.actorOf(Props[Pinger], "pinger")
            val ponger = system.actorOf(Props[Ponger], "ponger")




                                                                   @jamie_allen

アクターには名前を付けること
Saturday, March 2, 13
Create	
  Specialized	
  Messages
         •Non-­‐specific	
  messages	
  about	
  general	
  events	
  
                are	
  dangerous
                                       AccountsUpdated

         •Can	
  result	
  in	
  "event	
  storms"	
  as	
  all	
  actors	
  react	
  to	
  
                them

         •Use	
  specific	
  messages	
  forwarded	
  to	
  actors	
  for	
  
                handling
                        AccountDeviceAdded(acctNum, deviceNum)


                                                                             @jamie_allen

専用メッセージを作る。汎用イベントは危険。
Saturday, March 2, 13
Create	
  Specialized	
  Exceptions


         •Don't	
  use	
  java.lang.Exception	
  to	
  represent	
  
                failure	
  in	
  an	
  actor

         •Specific	
  exceptions	
  can	
  be	
  handled	
  explicitly
         •State	
  can	
  be	
  transferred	
  between	
  actor	
  
                incarnations	
  in	
  Akka	
  (if	
  need	
  be)


                                                                   @jamie_allen

専用例外を作る
Saturday, March 2, 13
Takeaway

         •Be	
  specific	
  in	
  everything	
  you	
  do
         •Makes	
  everything	
  that	
  occurs	
  in	
  your	
  actor	
  
                system	
  more	
  clear	
  to	
  other	
  developers	
  
                maintaining	
  the	
  code

         •Makes	
  everything	
  more	
  clear	
  in	
  production

                                                                           @jamie_allen

全てにおいて特定であること。本番環境でも役立つ。
Saturday, March 2, 13
RULE:
                        Do Not Expose Your Actors



                                                    @jamie_allen

アクターを公開しないこと
Saturday, March 2, 13
No	
  Direct	
  References

         •Actors	
  die
         •Doesn't	
  prevent	
  someone	
  from	
  calling	
  into	
  an	
  
                actor	
  with	
  another	
  thread

         •Akka	
  solves	
  this	
  with	
  the	
  ActorRef	
  abstraction
         •Erlang	
  solves	
  this	
  with	
  PIDs
                                                                   @jamie_allen

絶対にアクターを直接参照してはいけない
Saturday, March 2, 13
Never	
  Publish	
  “this”

         •Don't	
  send	
  it	
  anywhere
         •Don't	
  register	
  it	
  anywhere
         •Particularly	
  with	
  future	
  callbacks
         •Publish	
  “self”	
  instead,	
  which	
  is	
  an	
  ActorRef
         •Avoid	
  closing	
  over	
  "sender"	
  in	
  Akka,	
  it	
  will	
  
                change	
  with	
  the	
  next	
  message

                                                                          @jamie_allen

絶対に this を返してはいけない。代わりに self を使う。
Saturday, March 2, 13
Use	
  Immutable	
  Messages


         •Enforces	
  which	
  actor	
  owns	
  the	
  data
         •If	
  mutable	
  state	
  can	
  escape,	
  what	
  is	
  the	
  point	
  
                of	
  using	
  an	
  actor?




                                                                           @jamie_allen

不変メッセージを使うこと
Saturday, March 2, 13
Pass	
  Copies	
  of	
  Mutable	
  Data

         •Mutable	
  data	
  in	
  actors	
  is	
  fine
         •But	
  data	
  can	
  escape	
  your	
  scope
         •Copy	
  the	
  data	
  and	
  pass	
  that,	
  as	
  Erlang	
  does	
  
                (COW)

         •Akka	
  has	
  STM	
  references
                                                                           @jamie_allen

可変データはコピーを送る
Saturday, March 2, 13
Avoid	
  Sending	
  Behavior


         •Unless	
  using	
  Agents,	
  of	
  course
         •Closures	
  make	
  this	
  possible	
  (and	
  easy)
         •Also	
  makes	
  it	
  easy	
  for	
  state	
  to	
  escape

                                                                        @jamie_allen

振る舞いを送ることは避ける
Saturday, March 2, 13
Takeaway


         •Keep	
  everything	
  about	
  an	
  actor	
  internal	
  to	
  that	
  
                actor

         •Be	
  vary	
  wary	
  of	
  data	
  passed	
  in	
  closures	
  to	
  
                anyone	
  else



                                                                             @jamie_allen

アクターの内部構造を外に見せないこと
Saturday, March 2, 13
RULE:
                Make Debugging Easy On Yourself



                                            @jamie_allen

デバッギングが簡単にできるようにする
Saturday, March 2, 13
Externalize	
  Business	
  Logic

         •Consider	
  using	
  external	
  functions	
  to	
  
                encapsulate	
  complex	
  business	
  logic

         •Easier	
  to	
  unit	
  test	
  outside	
  of	
  actor	
  context
         •Not	
  a	
  rule	
  of	
  thumb,	
  but	
  something	
  to	
  consider	
  
                as	
  complexity	
  increases

         •Not	
  as	
  big	
  of	
  an	
  issue	
  with	
  Akka's	
  TestKit
                                                                           @jamie_allen

ビジネス・ロジックは外に書く
Saturday, March 2, 13
Use	
  Semantically	
  Useful	
  Logging


         •Trace-­‐level	
  logs	
  should	
  have	
  output	
  that	
  you	
  
                can	
  read	
  easily

         •Use	
  line-­‐breaks	
  and	
  indentation
         •Both	
  Akka	
  and	
  Erlang	
  support	
  hooking	
  in	
  
                multiple	
  listeners	
  to	
  the	
  event	
  log	
  stream


                                                                           @jamie_allen

読んで意味のあるログを書く
Saturday, March 2, 13
Unique	
  IDs	
  for	
  Messages
         •Allows	
  you	
  to	
  track	
  message	
  flow
         •When	
  you	
  find	
  a	
  problem,	
  get	
  the	
  ID	
  of	
  the	
  
                message	
  that	
  led	
  to	
  it

         •Use	
  the	
  ID	
  to	
  grep	
  your	
  logs	
  and	
  display	
  output	
  
                just	
  for	
  that	
  message	
  flow

         •Akka	
  ensures	
  ordering	
  on	
  a	
  per	
  actor	
  basis,	
  also	
  
                in	
  logging

                                                                             @jamie_allen

メッセージにユニークIDをふる
Saturday, March 2, 13
Monitor	
  Everything
         •Do	
  it	
  from	
  the	
  start
         •Use	
  tools	
  like	
  JMX	
  MBeans	
  to	
  visualize	
  actor	
  
                realization

         •The	
  Typesafe	
  Console	
  is	
  a	
  great	
  tool	
  to	
  visualize	
  
                actor	
  systems,	
  doesn't	
  require	
  you	
  to	
  do	
  
                anything	
  up	
  front

         •Visual	
  representations	
  of	
  actor	
  systems	
  at	
  
                runtime	
  are	
  invaluable
                                                                             @jamie_allen

全てを監視する
Saturday, March 2, 13
Typesafe	
  Console




                                              @jamie_allen


Saturday, March 2, 13
Takeaway


         •Build	
  your	
  actor	
  system	
  to	
  be	
  maintainable	
  
                from	
  the	
  outset

         •Utilize	
  all	
  of	
  the	
  tools	
  at	
  your	
  disposal

                                                                           @jamie_allen

メンテが容易なアクターシステムを構築する
Saturday, March 2, 13
Thank	
  You!

         •Some	
  content	
  provided	
  by	
  members	
  of	
  the	
  
                Typesafe	
  team,	
  including:

               •Jonas	
  Bonér
               •Viktor	
  Klang
               •Roland	
  Kuhn
               •Havoc	
  Pennington
                                                                  @jamie_allen

ご清聴ありがとうございました
Saturday, March 2, 13

More Related Content

More from shinolajla

20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdasshinolajla
 
20160317 lagom sf scala
20160317 lagom sf scala20160317 lagom sf scala
20160317 lagom sf scalashinolajla
 
Effective Akka v2
Effective Akka v2Effective Akka v2
Effective Akka v2shinolajla
 
20150411 mutability matrix of pain scala
20150411 mutability matrix of pain scala20150411 mutability matrix of pain scala
20150411 mutability matrix of pain scalashinolajla
 
Reactive applications tools of the trade huff po
Reactive applications   tools of the trade huff poReactive applications   tools of the trade huff po
Reactive applications tools of the trade huff poshinolajla
 
20140228 fp and_performance
20140228 fp and_performance20140228 fp and_performance
20140228 fp and_performanceshinolajla
 
Effective akka scalaio
Effective akka scalaioEffective akka scalaio
Effective akka scalaioshinolajla
 
Real world akka recepies v3
Real world akka recepies v3Real world akka recepies v3
Real world akka recepies v3shinolajla
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scalashinolajla
 

More from shinolajla (11)

20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas20160520 what youneedtoknowaboutlambdas
20160520 what youneedtoknowaboutlambdas
 
20160317 lagom sf scala
20160317 lagom sf scala20160317 lagom sf scala
20160317 lagom sf scala
 
Effective Akka v2
Effective Akka v2Effective Akka v2
Effective Akka v2
 
20150411 mutability matrix of pain scala
20150411 mutability matrix of pain scala20150411 mutability matrix of pain scala
20150411 mutability matrix of pain scala
 
Reactive applications tools of the trade huff po
Reactive applications   tools of the trade huff poReactive applications   tools of the trade huff po
Reactive applications tools of the trade huff po
 
20140228 fp and_performance
20140228 fp and_performance20140228 fp and_performance
20140228 fp and_performance
 
Effective akka scalaio
Effective akka scalaioEffective akka scalaio
Effective akka scalaio
 
Cpu Caches
Cpu CachesCpu Caches
Cpu Caches
 
Real world akka recepies v3
Real world akka recepies v3Real world akka recepies v3
Real world akka recepies v3
 
Taxonomy of Scala
Taxonomy of ScalaTaxonomy of Scala
Taxonomy of Scala
 
CPU Caches
CPU CachesCPU Caches
CPU Caches
 

Recently uploaded

Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfAnna Loughnan Colquhoun
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024SkyPlanner
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdfPedro Manuel
 
Things you didn't know you can use in your Salesforce
Things you didn't know you can use in your SalesforceThings you didn't know you can use in your Salesforce
Things you didn't know you can use in your SalesforceMartin Humpolec
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAshyamraj55
 
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataSafe Software
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UbiTrack UK
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Websitedgelyza
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxMatsuo Lab
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaborationbruanjhuli
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...Aggregage
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxGDSC PJATK
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxYounusS2
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioChristian Posta
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding TeamAdam Moalla
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IES VE
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.YounusS2
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsSeth Reyes
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIUdaiappa Ramachandran
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPathCommunity
 

Recently uploaded (20)

Spring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdfSpring24-Release Overview - Wellingtion User Group-1.pdf
Spring24-Release Overview - Wellingtion User Group-1.pdf
 
Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024Salesforce Miami User Group Event - 1st Quarter 2024
Salesforce Miami User Group Event - 1st Quarter 2024
 
Nanopower In Semiconductor Industry.pdf
Nanopower  In Semiconductor Industry.pdfNanopower  In Semiconductor Industry.pdf
Nanopower In Semiconductor Industry.pdf
 
Things you didn't know you can use in your Salesforce
Things you didn't know you can use in your SalesforceThings you didn't know you can use in your Salesforce
Things you didn't know you can use in your Salesforce
 
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPAAnypoint Code Builder , Google Pub sub connector and MuleSoft RPA
Anypoint Code Builder , Google Pub sub connector and MuleSoft RPA
 
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial DataCloud Revolution: Exploring the New Wave of Serverless Spatial Data
Cloud Revolution: Exploring the New Wave of Serverless Spatial Data
 
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
UWB Technology for Enhanced Indoor and Outdoor Positioning in Physiological M...
 
COMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a WebsiteCOMPUTER 10 Lesson 8 - Building a Website
COMPUTER 10 Lesson 8 - Building a Website
 
Introduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptxIntroduction to Matsuo Laboratory (ENG).pptx
Introduction to Matsuo Laboratory (ENG).pptx
 
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online CollaborationCOMPUTER 10: Lesson 7 - File Storage and Online Collaboration
COMPUTER 10: Lesson 7 - File Storage and Online Collaboration
 
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
The Data Metaverse: Unpacking the Roles, Use Cases, and Tech Trends in Data a...
 
Cybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptxCybersecurity Workshop #1.pptx
Cybersecurity Workshop #1.pptx
 
Babel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptxBabel Compiler - Transforming JavaScript for All Browsers.pptx
Babel Compiler - Transforming JavaScript for All Browsers.pptx
 
Comparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and IstioComparing Sidecar-less Service Mesh from Cilium and Istio
Comparing Sidecar-less Service Mesh from Cilium and Istio
 
9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team9 Steps For Building Winning Founding Team
9 Steps For Building Winning Founding Team
 
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
IESVE Software for Florida Code Compliance Using ASHRAE 90.1-2019
 
Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.Basic Building Blocks of Internet of Things.
Basic Building Blocks of Internet of Things.
 
Computer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and HazardsComputer 10: Lesson 10 - Online Crimes and Hazards
Computer 10: Lesson 10 - Online Crimes and Hazards
 
RAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AIRAG Patterns and Vector Search in Generative AI
RAG Patterns and Vector Search in Generative AI
 
UiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation DevelopersUiPath Community: AI for UiPath Automation Developers
UiPath Community: AI for UiPath Automation Developers
 

Effective actors japanesesub

  • 1. Effective  Actors Jamie  Allen Saturday, March 2, 13
  • 2. Who  Am  I? •Consultant  at  Typesafe •Actor  &  Scala  developer  since  2009 jamie.allen@typesafe.com @jamie_allen Typesafe 社でコンサルタントしています Saturday, March 2, 13
  • 3. Effective  Actors •Best  practices  based  on  several  years  of  actor   development •Helpful  hints  for  reasoning  about  actors  at  runtime @jamie_allen 何年かの開発に基づいたベスト・プラクティスとヒント Saturday, March 2, 13
  • 4. Actors •Concurrent,   A lightweight   processes  that   communicate   B C through   asynchronous   D message  passing •Isolation  of  state,  no   E F G internal  concurrency 非同期なメッセージを用いて対話する並行プロセス @jamie_allen 状態の隔離 Saturday, March 2, 13
  • 5. Akka  Actors class Pinger extends Actor { def receive = { case "Pong" => println("Pinging!"); sender ! "Ping!" } } class Ponger extends Actor { def receive = { case "Ping" => println("Ponging!"); sender ! "Pong!" } } object PingPong extends App { val system = ActorSystem() val pinger = system.actorOf(Props[Pinger]) val ponger = system.actorOf(Props[Ponger]) pinger.tell("Pong!", ponger) Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 6. Akka  Actors class Pinger extends Actor { def receive = { case "Pong" => println("Pinging!"); sender ! "Ping!" } } class Ponger extends Actor { def receive = { case "Ping" => println("Ponging!"); sender ! "Pong!" } } object PingPong extends App { val system = ActorSystem() val pinger = system.actorOf(Props[Pinger]) val ponger = system.actorOf(Props[Ponger]) pinger.tell("Pong!", ponger) Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 7. Akka  Actors class Pinger extends Actor { def receive = { case "Pong" => println("Pinging!"); sender ! "Ping!" } } class Ponger extends Actor { def receive = { case "Ping" => println("Ponging!"); sender ! "Pong!" } } object PingPong extends App { val system = ActorSystem() val pinger = system.actorOf(Props[Pinger]) val ponger = system.actorOf(Props[Ponger]) pinger.tell("Pong!", ponger) Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 8. Akka  Actors class Pinger extends Actor { def receive = { case "Pong" => println("Pinging!"); sender ! "Ping!" } } class Ponger extends Actor { def receive = { case "Ping" => println("Ponging!"); sender ! "Pong!" } } object PingPong extends App { val system = ActorSystem() val pinger = system.actorOf(Props[Pinger]) val ponger = system.actorOf(Props[Ponger]) pinger.tell("Pong!", ponger) Thread.sleep(1000) system.shutdown } Overriding the “sender” @jamie_allen Saturday, March 2, 13
  • 9. Supervisor  Hierarchies A •Specifies  handling   B C mechanisms  for   groupings  of  actors   in  parent/child   D relationship E F G @jamie_allen Supervisor はアクター階層の処理を定義する Saturday, March 2, 13
  • 10. Akka  Supervisors class MySupervisor extends Actor { override val supervisorStrategy = OneForOneStrategy() { case ae: ArithmeticException => Resume case np: NullPointerException => Restart } context.actorOf(Props[MyActor]) } @jamie_allen Saturday, March 2, 13
  • 11. Akka  Supervisors class MySupervisor extends Actor { override val supervisorStrategy = OneForOneStrategy() { case ae: ArithmeticException => Resume case np: NullPointerException => Restart } context.actorOf(Props[MyActor]) } @jamie_allen Saturday, March 2, 13
  • 12. Akka  Supervisors class MySupervisor extends Actor { override val supervisorStrategy = OneForOneStrategy() { case ae: ArithmeticException => Resume case np: NullPointerException => Restart } context.actorOf(Props[MyActor]) } Note the “context” @jamie_allen Saturday, March 2, 13
  • 13. Domain  Supervision •Each  supervisor  manages  a  grouping  of  types  in   a  domain •Actors  persist  to  represent  existence  of   instances  and  contain  their  own  state •Actors  constantly  resolve  the  world  as  it  should   be  against  the  world  as  it  is @jamie_allen Supervisor 階層を利用しドメインをモデルする Saturday, March 2, 13
  • 14. Worker  Supervision •Supervisors  should  hold  all  critical  data •Workers  should  receive  data  for  tasks  in   messages •Workers  being  supervised  should  perform   dangerous  tasks •Supervisor  should  know  how  to  handle  failures   in  workers  in  order  to  retry  appropriately Supervisor がデータを保持し、メッセージでワーカーに渡す @jamie_allen ワーカーは死んでも構わない Saturday, March 2, 13
  • 15. Parallelism •Easily  scale  a  task  by   A creating  multiple   instances  of  an  actor   and  applying  work   B C using  various   strategies D •Order  is  not   guaranteed,  nor   E F G should  it  be @jamie_allen 複数のアクターを作成することでタスクをスケール Saturday, March 2, 13
  • 16. Akka  Routing class MyActor extends Actor { def receive = { case x => println(x) } } object Parallelizer extends App { val system = ActorSystem() val router: ActorRef = system.actorOf(Props[MyActor]. withRouter(RoundRobinRouter(nrOfInstances = 5))) for (i <- 1 to 10) router ! i } @jamie_allen Saturday, March 2, 13
  • 17. Akka  Routing class MyActor extends Actor { def receive = { case x => println(x) } } object Parallelizer extends App { val system = ActorSystem() val router: ActorRef = system.actorOf(Props[MyActor]. withRouter(RoundRobinRouter(nrOfInstances = 5))) for (i <- 1 to 10) router ! i } @jamie_allen Saturday, March 2, 13
  • 18. Akka  Routing class MyActor extends Actor { def receive = { case x => println(x) } } object Parallelizer extends App { val system = ActorSystem() val router: ActorRef = system.actorOf(Props[MyActor]. withRouter(RoundRobinRouter(nrOfInstances = 5))) for (i <- 1 to 10) router ! i } Should be configured externally @jamie_allen Saturday, March 2, 13
  • 19. Akka  Routing class MyActor extends Actor { def receive = { case x => println(x) } } object Parallelizer extends App { val system = ActorSystem() val router: ActorRef = system.actorOf(Props[MyActor]. withRouter(RoundRobinRouter(nrOfInstances = 5))) for (i <- 1 to 10) router ! i } @jamie_allen Saturday, March 2, 13
  • 20. RULE: Actors Should Only Do One Thing @jamie_allen アクターは1つの事に特化すること Saturday, March 2, 13
  • 21. Single  Responsibility  Principle •Do  not  conflate  responsibilities  in  actors •Becomes  hard  to  define  the  boundaries  of   responsibility •Supervision  becomes  more  difficult  as  you   handle  more  possibilities •Debugging  becomes  very  difficult @jamie_allen 単一責任の原則: なんでもかんでも手を出さない Saturday, March 2, 13
  • 22. Supervision •Every  non-­‐leaf  node  is  technically  a  supervisor •Create  explicit  supervisors  under  each  node  for   each  type  of  child  to  be  managed @jamie_allen アクターの種類ごとに Supervisor を分けること Saturday, March 2, 13
  • 23. Conflated  Supervision C1 C2 Customers Accounts & Ac1 Ac2 D1 D2 D3 Devices A1 A2 A3 A4 Applications @jamie_allen 混ざってる Supervisor Saturday, March 2, 13
  • 24. Explicit  Supervision C1 C2 Customers DS Accounts & AS Devices Ac1 Ac2 D1 D2 D3 A1 A2 A3 A4 Applications @jamie_allen 明示的な Supervisor Saturday, March 2, 13
  • 25. Keep  the  Error  Kernel  Simple •Limit  the  number  of  supervisors  you  create  at   this  level •Helps  with  fault  tolerance  and  explicit  handling   of  errors  through  the  hierarchy •Akka  uses  synchronous  messaging  to  create   top-­‐level  actors @jamie_allen Error Kernel はシンプルに Saturday, March 2, 13
  • 26. Use  Failure  Zones •Multiple  isolated  zones  with  their  own   resources  (thread  pools,  etc) •Prevents  starvation  of  actors •Prevents  issues  in  one  branch  from  affecting   another @jamie_allen Failure Zone を使ってリソースを隔離する Saturday, March 2, 13
  • 27. Failure  Zones C1 C2 Customers AS DS Accounts & Devices Ac1 Ac2 D1 D2 D3 A1 A2 A3 A4 Applications @jamie_allen Saturday, March 2, 13
  • 28. Failure  Zones C1 C2 Customers AS DS Accounts & Devices Ac1 Ac2 D1 D2 D3 A1 A2 A3 A4 Applications @jamie_allen Saturday, March 2, 13
  • 29. Takeaway •Isolation  of  groups  of  actors  limits  the  effects   of  failure •For  reasonably  complex  actor  systems,  shallow   trees  are  a  smell  test •Actors  are  cheap  -­‐  use  them @jamie_allen アクターのグループを隔離することで障害の影響を抑える Saturday, March 2, 13
  • 30. RULE: Block Only When and Where You Must @jamie_allen 必要な時に、必要な場所のみでブロックすること Saturday, March 2, 13
  • 31. Consequences  of  Blocking •Eventually  results  in  actor  starvation  as  thread   pool  dries  up •Horrible  performance •Massive  waste  of  system  resources ブロッキングの行く末: 無くなるスレッド、飢えるアクター、 @jamie_allen 落ちる性能 Saturday, March 2, 13
  • 32. Futures class Worker extends Actor { def receive = { case s: Seq[Int] => sender ! s.reduce(_ + _) } } class Delegator extends Actor { implicit val timeout: Timeout = 2 seconds val worker = context.actorOf(Props[Worker]) def receive = { case "Start" => worker ? (1 to 100) map (x => println("Got value: %d".format(x))) } } object Bootstrapper extends App { val system = ActorSystem() val delegator = system.actorOf(Props[Delegator]) delegator ! "Start" Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 33. Futures class Worker extends Actor { def receive = { case s: Seq[Int] => sender ! s.reduce(_ + _) } } class Delegator extends Actor { implicit val timeout: Timeout = 2 seconds val worker = context.actorOf(Props[Worker]) def receive = { case "Start" => worker ? (1 to 100) map (x => println("Got value: %d".format(x))) } } object Bootstrapper extends App { val system = ActorSystem() val delegator = system.actorOf(Props[Delegator]) delegator ! "Start" Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 34. Futures class Worker extends Actor { def receive = { case s: Seq[Int] => sender ! s.reduce(_ + _) } } class Delegator extends Actor { implicit val timeout: Timeout = 2 seconds val worker = context.actorOf(Props[Worker]) def receive = { case "Start" => worker ? (1 to 100) map (x => println("Got value: %d".format(x))) } } object Bootstrapper extends App { val system = ActorSystem() val delegator = system.actorOf(Props[Delegator]) delegator ! "Start" Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 35. Futures class Worker extends Actor { def receive = { case s: Seq[Int] => sender ! s.reduce(_ + _) } } class Delegator extends Actor { implicit val timeout: Timeout = 2 seconds val worker = context.actorOf(Props[Worker]) def receive = { case "Start" => worker ? (1 to 100) map (x => println("Got value: %d".format(x))) } } object Bootstrapper extends App { val system = ActorSystem() val delegator = system.actorOf(Props[Delegator]) delegator ! "Start" Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 36. Futures class Worker extends Actor { def receive = { case s: Seq[Int] => sender ! s.reduce(_ + _) } } class Delegator extends Actor { implicit val timeout: Timeout = 2 seconds val worker = context.actorOf(Props[Worker]) def receive = { case "Start" => worker ? (1 to 100) map (x => println("Got value: %d".format(x))) } } object Bootstrapper extends App { val system = ActorSystem() val delegator = system.actorOf(Props[Delegator]) delegator ! "Start" Thread.sleep(1000) system.shutdown } @jamie_allen Saturday, March 2, 13
  • 37. Sequential  Futures val r: Future[Int] = for { a <- (service1 ? GetResult).mapTo[Int] b <- (service2 ? GetResult(a)).mapTo[Int] } yield a * b @jamie_allen 順次 Future Saturday, March 2, 13
  • 38. Sequential  Futures Type Safety val r: Future[Int] = for { a <- (service1 ? GetResult).mapTo[Int] b <- (service2 ? GetResult(a)).mapTo[Int] } yield a * b @jamie_allen 順次 Future Saturday, March 2, 13
  • 39. Parallel  Futures First way: Define futures first val f1: Future[Int] = service1 ? GetResult val f2: Future[Int] = service2 ? GetResult val r: Future[Int] = for { a <- f1 b <- f2 } yield a * b @jamie_allen 並列 Future 方法1: 事前に Future を定義 Saturday, March 2, 13
  • 40. Parallel  Futures Second way: Define in one line of for comprehension val r: Future[Int] = for { (a: Int, b: Int) <- (service1 ? GetResult) zip (service2 ? GetResult) } yield a * b Note the “zip” @jamie_allen 並列 Future 方法2: zip を使って 1行で定義 Saturday, March 2, 13
  • 41. Blocking •An  example  is  database  access •Use  a  specialized  actor  with  its  own  resources •Pass  messages  to  other  actors  to  handle  the   result •Scala  provides  “Managed  Blocking”  to  limit  the   number  of  blocking  operations  taking  place  in   actors  at  one  time @jamie_allen ブロッキング専門のアクターを作る Saturday, March 2, 13
  • 42. Akka  Dispatcher class Worker extends Actor { def receive = { case s: Seq[Int] => sender ! s.reduce(_ + _) } } class Delegator extends Actor { implicit val timeout: Timeout = 2 seconds val worker = context.actorOf(Props[Worker]). withDispatcher(“my-dispatcher”) Failure def receive = { case _ => Zone blocking { val futResult = worker ? (1 to 100) val result = Await.result(futResult, 2 seconds) } } } @jamie_allen Saturday, March 2, 13
  • 43. Push,  Not  Pull •Start  with  no  guarantees  about  delivery •Add  guarantees  only  where  you  need  them •Retry  until  you  get  the  answer  you  expect •Switch  your  actor  to  a  "nominal"  state  at  that   point @jamie_allen 配達時間はまず保証無しから始める Saturday, March 2, 13
  • 44. Takeaway •Find  ways  to  ensure  that  your  actors  remain   asynchronous  and  non-­‐blocking •Avoid  making  your  actors  wait  for  anything   while  handling  a  message @jamie_allen アクターが非同期で非ブロッキングであるように努めること Saturday, March 2, 13
  • 45. RULE: Do Not Optimize Prematurely @jamie_allen 早すぎる最適化はダメ Saturday, March 2, 13
  • 46. Start  Simple •Make  Donald  Knuth  happy •Start  with  a  simple  configuration  and  profile •Do  not  parallelize  until  you  know  you  need  to   and  where @jamie_allen プロファイルも取らずに並列化しないこと Saturday, March 2, 13
  • 47. Initial  Focus •Deterministic •Declarative •Immutable •Start  with  functional  programming  and  go   from  there @jamie_allen まずは決定的、宣言型、不変など関数型の基本から Saturday, March 2, 13
  • 48. Advice  From  Jonas  Bonér •Layer  in  complexity •Add  indeterminism •Add  mutability  in  hot  spots   (CAS  and  STM) •Add  explicit  locking  and   threads  as  a  last  resort Photo courtesy of Brian Clapper, NE Scala 2011 段階的に複雑さを導入する: 1. 非決定性 2. 可変性 @jamie_allen 3. スレッドと明示的なロックは最終手段 Saturday, March 2, 13
  • 49. Prepare  for  Race  Conditions •Write  actor  code  to  be  agnostic  of  time  and   order •Actors  should  only  care  about  now,  not  that   something  happened  before  it •Actors  can  "become"  or  represent  state   machines  to  represent  transitions @jamie_allen アクターは時間と順序に無関心であるべき Saturday, March 2, 13
  • 50. Beware  the  Thundering  Herd •Actor  systems  can  be  overwhelmed  by  "storms"  of   messages  flying  about •Do  not  pass  generic  messages  that  apply  to  many   actors •Dampen  actor  messages  if  the  exact  same  message  is   being  handled  repeatedly  within  a  certain  timeframe •Tune  your  dispatchers  and  mailboxes  via  back-­‐off   policies  and  queue  sizes •Akka  now  has  Circuit  Breakers メッセージの「嵐」に注意 @jamie_allen 複数のアクターに作用する汎用メッセージは避ける Saturday, March 2, 13
  • 51. Takeaway •Start  by  thinking  in  terms  of  an  implementation   that  is  deterministic  and  not  actor  based •Layer  in  complexity  as  you  go @jamie_allen まずはアクターを使わない決定的な実装から Saturday, March 2, 13
  • 52. RULE: Be Explicit In Your Intent @jamie_allen 意図をハッキリさせること Saturday, March 2, 13
  • 53. Name  Your  Actors •Allows  for  external  configuration •Allows  for  lookup •Better  semantic  logging val system = ActorSystem("pingpong") val pinger = system.actorOf(Props[Pinger], "pinger") val ponger = system.actorOf(Props[Ponger], "ponger") @jamie_allen アクターには名前を付けること Saturday, March 2, 13
  • 54. Create  Specialized  Messages •Non-­‐specific  messages  about  general  events   are  dangerous AccountsUpdated •Can  result  in  "event  storms"  as  all  actors  react  to   them •Use  specific  messages  forwarded  to  actors  for   handling AccountDeviceAdded(acctNum, deviceNum) @jamie_allen 専用メッセージを作る。汎用イベントは危険。 Saturday, March 2, 13
  • 55. Create  Specialized  Exceptions •Don't  use  java.lang.Exception  to  represent   failure  in  an  actor •Specific  exceptions  can  be  handled  explicitly •State  can  be  transferred  between  actor   incarnations  in  Akka  (if  need  be) @jamie_allen 専用例外を作る Saturday, March 2, 13
  • 56. Takeaway •Be  specific  in  everything  you  do •Makes  everything  that  occurs  in  your  actor   system  more  clear  to  other  developers   maintaining  the  code •Makes  everything  more  clear  in  production @jamie_allen 全てにおいて特定であること。本番環境でも役立つ。 Saturday, March 2, 13
  • 57. RULE: Do Not Expose Your Actors @jamie_allen アクターを公開しないこと Saturday, March 2, 13
  • 58. No  Direct  References •Actors  die •Doesn't  prevent  someone  from  calling  into  an   actor  with  another  thread •Akka  solves  this  with  the  ActorRef  abstraction •Erlang  solves  this  with  PIDs @jamie_allen 絶対にアクターを直接参照してはいけない Saturday, March 2, 13
  • 59. Never  Publish  “this” •Don't  send  it  anywhere •Don't  register  it  anywhere •Particularly  with  future  callbacks •Publish  “self”  instead,  which  is  an  ActorRef •Avoid  closing  over  "sender"  in  Akka,  it  will   change  with  the  next  message @jamie_allen 絶対に this を返してはいけない。代わりに self を使う。 Saturday, March 2, 13
  • 60. Use  Immutable  Messages •Enforces  which  actor  owns  the  data •If  mutable  state  can  escape,  what  is  the  point   of  using  an  actor? @jamie_allen 不変メッセージを使うこと Saturday, March 2, 13
  • 61. Pass  Copies  of  Mutable  Data •Mutable  data  in  actors  is  fine •But  data  can  escape  your  scope •Copy  the  data  and  pass  that,  as  Erlang  does   (COW) •Akka  has  STM  references @jamie_allen 可変データはコピーを送る Saturday, March 2, 13
  • 62. Avoid  Sending  Behavior •Unless  using  Agents,  of  course •Closures  make  this  possible  (and  easy) •Also  makes  it  easy  for  state  to  escape @jamie_allen 振る舞いを送ることは避ける Saturday, March 2, 13
  • 63. Takeaway •Keep  everything  about  an  actor  internal  to  that   actor •Be  vary  wary  of  data  passed  in  closures  to   anyone  else @jamie_allen アクターの内部構造を外に見せないこと Saturday, March 2, 13
  • 64. RULE: Make Debugging Easy On Yourself @jamie_allen デバッギングが簡単にできるようにする Saturday, March 2, 13
  • 65. Externalize  Business  Logic •Consider  using  external  functions  to   encapsulate  complex  business  logic •Easier  to  unit  test  outside  of  actor  context •Not  a  rule  of  thumb,  but  something  to  consider   as  complexity  increases •Not  as  big  of  an  issue  with  Akka's  TestKit @jamie_allen ビジネス・ロジックは外に書く Saturday, March 2, 13
  • 66. Use  Semantically  Useful  Logging •Trace-­‐level  logs  should  have  output  that  you   can  read  easily •Use  line-­‐breaks  and  indentation •Both  Akka  and  Erlang  support  hooking  in   multiple  listeners  to  the  event  log  stream @jamie_allen 読んで意味のあるログを書く Saturday, March 2, 13
  • 67. Unique  IDs  for  Messages •Allows  you  to  track  message  flow •When  you  find  a  problem,  get  the  ID  of  the   message  that  led  to  it •Use  the  ID  to  grep  your  logs  and  display  output   just  for  that  message  flow •Akka  ensures  ordering  on  a  per  actor  basis,  also   in  logging @jamie_allen メッセージにユニークIDをふる Saturday, March 2, 13
  • 68. Monitor  Everything •Do  it  from  the  start •Use  tools  like  JMX  MBeans  to  visualize  actor   realization •The  Typesafe  Console  is  a  great  tool  to  visualize   actor  systems,  doesn't  require  you  to  do   anything  up  front •Visual  representations  of  actor  systems  at   runtime  are  invaluable @jamie_allen 全てを監視する Saturday, March 2, 13
  • 69. Typesafe  Console @jamie_allen Saturday, March 2, 13
  • 70. Takeaway •Build  your  actor  system  to  be  maintainable   from  the  outset •Utilize  all  of  the  tools  at  your  disposal @jamie_allen メンテが容易なアクターシステムを構築する Saturday, March 2, 13
  • 71. Thank  You! •Some  content  provided  by  members  of  the   Typesafe  team,  including: •Jonas  Bonér •Viktor  Klang •Roland  Kuhn •Havoc  Pennington @jamie_allen ご清聴ありがとうございました Saturday, March 2, 13