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

EIPとAkkaについて

 EIPとAkkaについて

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

かとじゅん
PRO

February 07, 2022
Tweet

More Decks by かとじゅん

Other Decks in Programming

Transcript

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  11. この問題は
    「信頼性の低い通信路」
    で何が起きるかを示している
    11

    View Slide

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

    View Slide

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

    将軍A
    将軍A
    敵地
    敵地
    将軍B
    将軍B
    14時に攻撃する
    了解
    なので、将軍Bは「了解」ということをメッセンジャーを通じて返
    信もらう必要がある(返信が来ない場合はリトライするかも)
    13

    View Slide

  14. 二人の将軍問題(4/4)
    が、これもメッセージが将軍Aに届かない可能性がある
    厳密には「了解」が伝わったかは、将軍Aからの「了解の了解」
    の返信を待つ必要がある…
    将軍A
    将軍A
    敵地
    敵地
    将軍B
    将軍B
    14時に攻撃する
    了解
    了解の了解??
    これでは 完全に合意するには無限のメッセージを送る必要があ
    る…
    14

    View Slide

  15. 低信頼網では
    100%の合意に到達できない
    どんなに多くの要求を送っても、どんなに多くの返答を送っても、
    将軍Aも将軍Bも相手の将軍が攻撃の準備をしていることを100%
    確信することはできません。
    これが「二人の将軍問題」の核心です
    15

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    運がよかったら届くかもね!
    そんなインテグレーションで大丈夫か?!
    19

    View Slide

  20. そこでEIPですよ
    20

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

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

    View Slide

  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

    View Slide

  34. この設計の問題点
    リトライ間隔やリトライ上限回数がないので、リトライによって
    ネットワークに負荷をかける可能性がある
    Akkaでは指数関数バックオフに対応したBackoffSupervisorに
    よって解決できる
    メッセージの追い越しできない場合は、メッセージを蓄積しつつ
    フロー制御が必要になる
    AkkaのStashBufferでバッファリングしつつ、
    akka-persistenceの機能によって受け付けたメッセージを蓄
    積する
    このサンプルでは、故障しやすいタスクをReceiverが担う場
    合、故障中のメッセージ配送をどうするかという問題がある
    EIPのように受信側にも故障しにくい仲介者が必要。仲介者と
    してSupervisorを間にいれる
    Akka Reliable Deliverも選択肢の一つ
    34

    View Slide

  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

    View Slide

  36. まとめ
    一般的にメッセージ配送には保証がない(TCPもHTTPもat-most-
    once)
    その代わりに高パフォーマンス・低コスト
    ちゃんと届けるにはそれなりの仕組みが必要になる
    それが配送保証(Guaranteed Delivery)
    配送保証(Guaranteed Delivery)によってat-leaset-onceを実
    現する
    Akkaには、配送保証(Guaranteed Delivery)の考え方が設計思想
    に組み込まれている
    PersistentActorでも実現可能
    Akka組込のReliable Deliveryを使うことも可能
    36

    View Slide

  37. 終わり
    37

    View Slide