Upgrade to Pro — share decks privately, control downloads, hide ads and more …

EIPとAkkaについて

 EIPとAkkaについて

EIPはメッセージングのためのデザインパターンです。インターネットもメッセージングで成り立っていますので、インターネットそのものがEIPのコンテキストと言っても過言ではありません。EIPは今どきの分散するシステムを設計する開発者として知っておいて損はありません。そんな偉大なEIPは、私が日常的に利用している分散システムのためのツールキットAkkaでもよく目にします。今回はその代表例を挙げて、EIPの考え方がどんなところで有用なのかを解説します。

933291444e456bfb511a66a2fa9c6929?s=128

かとじゅん

February 07, 2022
Tweet

More Decks by かとじゅん

Other Decks in Programming

Transcript

  1. EIPとAKKAについて かとじゅん( ) 2022/02/09 実践!インテグレーションパターン 現場から学ぶモデル駆動設計 @j5ik2o 1

  2. 自己紹介 Chatwork社 テックリード 副業では技術顧問として活動中 FizzBuzzを書くためだけのプログラミング言語を作りました @j5ik2o https://github.com/j5ik2o/oni-comb-rs 2

  3. EIPとAKKAについて話します 3

  4. 具体的には 配送保証(GUARANTEED DELIVERY) のパターンを解説します が、前提知識を少し話します。 4

  5. AGENDA 通信は届かない(ことがある) メッセージ配送の保証 配送保証(Guaranteed Delivery) Akkaの簡単な実装例とReliable Delivery 5

  6. 送信したデータが 相手に必ず届くと 思い込んでませんか? 6

  7. 通信は届かない(ことがある) 少なくとも現時点では失敗のないネットワークを構築することは 不可能と言われている。メッセージが欠落したり、遅延したりす る可能性は必ずある。今の技術で避けられない よく考えられたシステムは、この問題をカバーするように設計さ れている(それでも限界がある)。そのような考慮がないシステム では容易にメッセージの欠落や矛盾が起こる 7

  8. 「なぜ届かないのか」を理解する 8

  9. アナロジー:二人の将軍問題 信頼性の低い通信チャネルでは コンセンサスに達することが不可能である Two Generals' Problem 二人の将軍問題 9

  10. 二人の将軍問題(1/4) 赤が敵軍、緑が同盟軍。同盟軍A or Bが単独攻撃しても数で負け るが、AとB 一緒に攻撃すれば勝てる可能性がある。しかし、軍 隊は谷間に位置しているため、旗などの遠隔通信で攻撃の時間を 指示することは不可能 彼らはコミュニケーションのために敵地を経由して使者(メッセ ンジャー)を送る。が、敵地を経由するので使者は捕まったり殺

    されたりする可能性がある ⼭ ⼭ 敵軍 同盟軍A 同盟軍B 10
  11. この問題は 「信頼性の低い通信路」 で何が起きるかを示している 11

  12. 二人の将軍問題(2/4) 将軍Aから将軍Bに「14時に攻撃する」ということをメッセンジ ャーを通じて送る。 無事に将軍Bにメッセージが届いた場合 メッセンジャーは無事に 敵地を通り抜けて、将軍Bにメッセージを伝える。 将軍A 将軍A 敵地 敵地

    将軍B 将軍B 14時に攻撃する 12
  13. 二人の将軍問題(3/4) 将軍Bから将軍Aに返信がない場合、将軍Aはどう考えるか 将軍Aはメッセンジャーが将軍Bに到着したかを知らない。敵地 で殺されたかもしれない。将軍Bは「14時に攻撃する」を知らな い可能性がある。将軍Bが攻撃の準備ができていないかもしれな い 将軍A 将軍A 敵地 敵地

    将軍B 将軍B 14時に攻撃する 了解 なので、将軍Bは「了解」ということをメッセンジャーを通じて返 信もらう必要がある(返信が来ない場合はリトライするかも) 13
  14. 二人の将軍問題(4/4) が、これもメッセージが将軍Aに届かない可能性がある 厳密には「了解」が伝わったかは、将軍Aからの「了解の了解」 の返信を待つ必要がある… 将軍A 将軍A 敵地 敵地 将軍B 将軍B

    14時に攻撃する 了解 了解の了解?? これでは 完全に合意するには無限のメッセージを送る必要があ る… 14
  15. 低信頼網では 100%の合意に到達できない どんなに多くの要求を送っても、どんなに多くの返答を送っても、 将軍Aも将軍Bも相手の将軍が攻撃の準備をしていることを100% 確信することはできません。 これが「二人の将軍問題」の核心です 15

  16. ネットワークを使った メッセージ配送も 信頼性の低い通信路を 使った通信の一つ 16

  17. メッセージ配送には これらを考慮したモデルがある 17

  18. メッセージ配送の信頼性(1/2) At-Most-Once Delivery メッセージは0回もしくは1回 配送される (tellの場合は)送ったけど相手に届かないことがある askによって返信を確認することはできる とはいえ、タイムアウトしたときリトライするなら、at- most-once以上のことをやろうとしている 高パフォーマンス・低コスト

    18
  19. メッセージ配送の信頼性(1/2) At-Least-Once Delivery メッセージは少なくとも1回配送が成功する 相手にメッセージが重複して届く可能性がある 送信側に必ずディスクが必要になる Exactly-Once Delivery メッセージは正確に1回だけ配送される 受信側にもディスクが必要になる

    デフォルトのメッセージ配送は「At-Most-Once Delivery」です。 運がよかったら届くかもね! そんなインテグレーションで大丈夫か?! 19
  20. そこでEIPですよ 20

  21. 配送保証(GUARANTEED DELIVERY) At-Least-Once Deliveryのために 21

  22. メッセージングシステムが故障して も、送信者がメッセージを確実に届 けられるようにするには? メッセージを配送するシステム=メッセージングシステム messaging system sender receiver 22

  23. メッセージの保存と転送のプロセス 非同期に動作するメッセージングは送信者・受信者、そしてそれ らを繋ぐネットワークが同時に動作している必要がない(同期型 のRPCは障害に弱い) メッセージングシステムがネットワークを利用できない場合、ネ ットワークが利用可能になるまでメッセージを保存すればよい。 受信者が利用できない場合も、メッセージを保存しておき、受信 者が利用できるようになるまでリトライする。 23

  24. 受信者が故障で不通なら 送信者はリトライする。 リトライ中 送信者が故障しても 大丈夫? 24

  25. いいえ 当然リトライ中であること も忘れます 25

  26. メッセージが揮発しないように メッセージを永続化する メッセージングシステムがノード障害などを起こせば、保持して いるメッセージはすべて消失する。 対策としてファイルやデータベースなどを使ってディスクに永続 化する必要がある Apache Kafkaがまさに同じようなことをやっています(ブローカー が仲介するので厳密には同じではないが) 26

  27. 配送保証(GUARANTEED DELIVERY) のPROS/CONS 配送保証パターンでは、メッセージングシステムはデータストア を使ってメッセージを保存します 27

  28. 送信者が故障しても 復旧後にメッセージは送信される 送信側のPCのローカルに保存されます。メッセージ送信際、デ ータストアにメッセージが保存されるまで送信操作は正常に完了 しない。メッセージが正常に送信されたら、データストアからメ ッセージが削除される 28

  29. 信頼性を得る代わりに パフォーマンスが犠牲になる メッセージの永続性は信頼性を高めるが、パフォーマンスが犠牲 になる。メッセージ配送のクラッシュやシャットダウン時にメッ セージが失われても構わない場合は、配送保証パターンを採用し ないほうがパフォーマンスがよくなる(トレードオフ) 29

  30. FYI: EXACTLY-ONCE DELIVERY = 配送保証(GUARANTEED DELIVERY) + べき等レシーバー(IDEMPOTENT RECEIVER) 30

  31. AKKAでどう実装するか 31

  32. 簡単なモデルを示した例 network Sender«Actor» Forwarder«PersistentActor» Receiver«Actor» 32

  33. 登場人物 Receiver Forwarder Sender https://github.com/j5ik2o/akka-at-least-once- delivery/blob/main/src/main/scala/example/simple/Receive https://github.com/j5ik2o/akka-at-least-once- delivery/blob/main/src/main/scala/example/simple/Forwar https://github.com/j5ik2o/akka-at-least-once- delivery/blob/main/src/test/scala/example/simple/AtLeastO

    33
  34. この設計の問題点 リトライ間隔やリトライ上限回数がないので、リトライによって ネットワークに負荷をかける可能性がある Akkaでは指数関数バックオフに対応したBackoffSupervisorに よって解決できる メッセージの追い越しできない場合は、メッセージを蓄積しつつ フロー制御が必要になる AkkaのStashBufferでバッファリングしつつ、 akka-persistenceの機能によって受け付けたメッセージを蓄 積する

    このサンプルでは、故障しやすいタスクをReceiverが担う場 合、故障中のメッセージ配送をどうするかという問題がある EIPのように受信側にも故障しにくい仲介者が必要。仲介者と してSupervisorを間にいれる Akka Reliable Deliverも選択肢の一つ 34
  35. AKKA RELIABLE DELIVERY https://doc.akka.io/docs/akka/current/typed/reliable- delivery.html https://github.com/j5ik2o/akka-at-least-once- delivery/tree/main/src/main/scala/example/delivery 35

  36. まとめ 一般的にメッセージ配送には保証がない(TCPもHTTPもat-most- once) その代わりに高パフォーマンス・低コスト ちゃんと届けるにはそれなりの仕組みが必要になる それが配送保証(Guaranteed Delivery) 配送保証(Guaranteed Delivery)によってat-leaset-onceを実 現する

    Akkaには、配送保証(Guaranteed Delivery)の考え方が設計思想 に組み込まれている PersistentActorでも実現可能 Akka組込のReliable Deliveryを使うことも可能 36
  37. 終わり 37