Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

Akka actorを何故使うのか?

819 views

Published on

Akka actorを何故使うのか?

Published in: Technology
  • Be the first to comment

Akka actorを何故使うのか?

  1. 1. AkkaのActorをなぜ使うのか? ~これから使う人向け~ ナイル株式会社 的場 勇樹
  2. 2. 自己紹介 名前: 的場勇樹 - 先ほど紹介のあったAppliv Platform (Applivのデータを統括的に扱うやつ) で Scalaを使って1年ほど開発をしていました。
  3. 3. Actorとは? メッセージでやりとりするエンティティー instance i1 instance i2 i2.method() Actor a1 Actor a2 a2 ! “message” 「このメッセージを受け取った らこういう処理をする」という 関数がこの中で定義されている a2に”message”というstring を送る
  4. 4. HelloActor MyActor 1. Hello 2. “what’s up?” 3. output “nothing” Actorを使い始めた頃、こういうのを実現するときに
  5. 5. こんなコードを書いてて...
  6. 6. こんなコードを書いてて...
  7. 7. これでええやんと一瞬思ってました
  8. 8. 「MyActor内の動作とHelloActor内の動作は 非同期になってるので、 非同期な処理を書きやすい」 って聞いたあとも
  9. 9. Futureでええやんとしばらく思ってました
  10. 10. Futureでええやんとしばらく思ってました
  11. 11. それでもなぜAkkaのActorを使うのか? → システムをReactiveにするため
  12. 12. Reactive Systemとは 以下の4つの要素に分けられる - 目的 = 即応性 (Responsive): すぐレスポンス返す!エラーすぐ見つける! - 戦略1 = 耐障害性 (Resilient): 障害に強い! - 戦略2 = 弾力性 (Elastic): 冗長化して負荷分散するのが簡単! - 戦術 = メッセージ駆動 (Message Driven): 各コンポーネントを疎結合にしや すくてリソースも節約できる! (戦略: 目的を達成するために注力すべきポイント) (戦術: 戦略で決めた部分を改善するために取る具体的な方法) 上の説明はざっくりしすぎて誤解を生む可能性がなくもないので、 詳細はリアクティブ宣言を参照。
  13. 13. なるほど、という感じではあるけど抽象的 なのでピンと来ない → 実例を挙げていって、何が便利なのかを 比べていきましょう
  14. 14. 1.Actor間の疎結合具合がすごい 疎結合だと何が良いのか → 遅延、障害の伝播を防ぐことができる → 耐障害性が高くなる まだ抽象的なので具体例を見ていきましょう。
  15. 15. Instance A Instance B 2.call B’s method Actorでないとき 1.call A’s method1 3.return value Main 4.call A’s method2 ごめん、めっちゃ時 間かかってるじゃあ待つわ method2の処理は? すいません、まだBからレ スポンス返ってこなく て・・ Instance Bの遅延が全体に波及して いる
  16. 16. Actor A Actor B 2.send message Actorであるとき 1.send message1 3.send back response Main 4.send message2 ごめん、めっちゃ時 間かかってる知らん message2の処理は? message1の処理終わった んで、すぐやります! Actor Bの遅延をActor B内に閉じ込めている。 (“4 send message2” の処理の影響がでない) これはまあFutureでも解決できる
  17. 17. Instance A Instance B 2.call B’s method Actorでないとき 1.call A’s method1 3.return value Main 4.call A’s method2 エラー出たので死に ます・・ その影響で俺 も・・ じゃあ俺も・・ Instance Bの遅延が全体に波及して いる
  18. 18. Actor A Actor B 2.send message Actorであるとき 1.send message1 3.send back response Main 4.send message2 エラー出たので死に ます!知らん message2の処理は? message1の処理終わった んで、すぐやります! Actor Bでの障害をActor B内に閉じ込 めれる (4の処理に影響が出ない) Actor Bに親アクターがいるとき、親 アクターがクラッシュ時の挙動を決 定できる (Let it crashの16ページ目か ら) ActorLogging, ScalaLogging などで、どのアクターでどん なエラーが出たのかは記録で きる 詳細
  19. 19. 2. Messageを順次処理するので過負荷を防げる 1. Actorに届けられたメッセージはそのActorのMessage Queueに格納される 2. Message Queueからメッセージを取り出す 3. そのメッセージに基づいた処理を開始 4. 現在の処理が終わったらMessage Queueから次のメッセージを取り出す って感じでActorは一つずつ処理をする 具体的に何が良いのか見ていきましょう。
  20. 20. Instance A Instance E 1. call E’s update method Actorでないとき Instance B DB 2. update by A’s request 1.call E’s update method Instance C 1.call E’s update method 2. update by B’s request 2. update by C’s request そんないっぺんにいっぱい来られて も無理。
  21. 21. Actor A Actor E 1. send update message Actorであるとき Actor B DB 2. update by A’s message 1.send update message Actor C 1.send update message 3. update by B’s message 4. update by C’s message 一つずつくるから、負荷も安心 ※デッドロックの心配もなし Actor間は非同期なので、Actor Eにメ ッセージが溜まっても他のActorには 関係なし UnboundedPriorityMailboxを使用する ことでメッセージの優先度も設定可 能 詳細
  22. 22. 3. 並列度の操作や冗長化が簡単 単一責務の原則に基づいてActorが設計されているとすると、 「ある処理が重い」 → 「その処理をしているActorを増やそう」 で解決することが多いはず。その増えたActorに処理を振り分ける方法が - Akka Router これ のスライドの37ページ目から - RemoteActor 詳細 - ClusterActor 詳細 などと、色々揃っているので順番に見ていきましょう
  23. 23. Router val actor = system.actorOf(Props[MyActor]) actor ! “message 1” actor ! “message 2” actor ! “message 3” val actor = system.actorOf(Props[MyActor].withRouter(RoundRobi nRouter(nOfInstances = 3)) actor ! “message 1” actor ! “message 2” actor ! “message 3” MyActor “message 1” “message 2” “message 3” MyActor MyActor MyActor Router “message 1” “message 2” “message 3” “message 2” “message 3” “message 1”
  24. 24. RemoteActor RouterでMyActorの並列度は操作できた → でもサーバー1台のリソースは限られているので、並列処理しすぎて過負荷に なってしまったとする →Actorを別のサーバーで動かしてそこにメッセージを投げたい RemoteActorなら、わざわざHTTPのAPIを用意しなくてもサーバーをまたいで Actorがメッセージをやりとりできる。 (各アクターにはPath(アドレス)があるので、そのPathを指定して、別サーバーの Actorを参照できる)
  25. 25. RemoteActor IP: 192.168.33.20 val system = ActorSystem(“my-system”) val actor = system.actorOf(Props[MyActor], “my- actor”) application.conf { /*他の設定も本当は書く*/ remote { hostname = “192.168.33.20” port = 2552 } } IP: 192.168.33.21 val system = ActorSystem(“my-system”) val path = “akka.tcp://my- system@192.168.33.20:2552/user/my-actor” //ActorSystem名、host, port, Actor名でActorの ユニークなアドレスを指定 val actor = system.actorSelection(path) //↑ で別サーバーにあるMyActorの参照を得た。 actor ! “message” //↑ で別サーバーにあるMyActorにメッセージを 投げている。
  26. 26. ClusterActor (cluster client) IP: 192.168.33.10IP: 192.168.33.11 ClusterClient “message” “message”
  27. 27. ClusterActor (cluster client) IP: 192.168.33.10IP: 192.168.33.11IP: 192.168.33.12 ClusterClient “message” seedを指定してActorSystemを起動
  28. 28. まとめ - Actorはメッセージ駆動なので、Reactive Systemを実現しやすくなる - Actor間はめっちゃ疎結合なので、遅延やエラーの伝播を防げる - Actorを使うことで負荷の調節が簡単にできる - サーバーをまたいでシステムを冗長化することも簡単にできる
  29. 29. 最後に AkkaにはActor以外にも(Akka Streamなど)、Reactive Systemを実現するためのラ イブラリが色々用意されていて、開発がかなり活発なので是非注目していきまし ょう。 Akka Streamの詳細 Akka Streamの詳細2 ご清聴ありがとうございました!

×