Amazon の Distributed Computing Manifesto をご存知でしょうか。私は知らなかったのですが、どうやら今年の Re:Invent Keynote Speech にて取り上げられたそうです。
現 Amazon CTO が 15 年前に読んで感銘を受けた文書だそうで、今後の AWS の進化にも関わってくるそうです。となれば気になるので読んでみたのですが、なるほどこれは深い……。ざーっとまとめてみます。
この記事は、 AWS Advent Calendar 2022 の18日目の記事です。
TL;DR
- Amazon 販売システムを世界レベルに拡張するための話だよ
- 以下のような、今じゃ当たり前になった概念について述べてるよ
- API ベースのサービス連携
- それぞれの責務を持ったマイクロサービス
- サービス間には Queue を入れる
- Workflow Coordinator が必要
- DB は Concern ごとに分離
- CGI 全盛以前の時代にこれ考えて AWS 作るまでになったのヤバだよ
内容
こちら↓にある論文の内容を、章ごとに意訳してまとめていきます。
凡例
意訳部分
コメント部分
Background
Amazon のアクセスが 10 倍になったときにも Amazon が動き続けるにはどうしたらいいのか。中央に巨大なデータベースがあるモデルを脱却する必要がある。
Key Concepts
二つのキーコンセプトがある。具体策はさておき、これらを適用していかなければならない
Service-based Model
アプリケーションが直接 DB を触るのをやめる。今後はアプリケーションは business logic を通じてのみデータストアへアクセスできるようにする。こうすることで、アプリケーションはデータストアと疎結合になり、 DB のスキーマや在処などを知らなくてよくなる。
SOA についての RedHat 文書を見るに、時代背景的には「多数のアプリケーションが密結合する環境」のこともモノリシックと表現されていたようだ。 RPC 呼び出しはあるにせよその実装は固定的だった時代に、そのモノリシックなアプリケーションを分割して API 連携させよう、データモデリングを行おう、と述べているのはまさに革新的 https://www.redhat.com/ja/topics/cloud-native-apps/what-is-service-oriented-architecture
また、同期的なアクセスもあれば非同期的なアクセスもあることに留意する。非同期の取り扱いは難しく、 callback モデルも考えられるが、 polling モデルがいいだろう。
Service-based model へ移行するにあたり、以下二点を考える必要がある。
- ソフトウェア開発をより規律正しく行なっていくこと。モノリシックで分離の悪いシステムから、最終的には3レイヤ構造へと変えていかなければならない
- data location transparency や、顧客影響のない DB migration を実現するため
- データ中心の考え方から、サービス中心の考え方へと移行していく。そのためには、以下の二つを実現していかなければならない
- データをモデリングすること。これまでやってきた通り
- 実際のデータをアプリケーションが知らなくて良いよう、データモデルのインターフェイスを定義すること。 これは今までやったことがない
data location transparency は、たとえば DB を MySQL から一部だけ memcached へと移動させたとか、そういうケースを考えると分かりやすそう。モノリシックで一層構造のアプリケーションで、データ構造が変わったら、あらゆる場所に散らばった SQL を修正しないといけない。これを避けるためにレイヤ構造を導入したい、と考えると、考えとしては確かにそうなんだがたぶん凄まじい改革になるだろうなと思わせる
Workflow-based Model and Data Domaining
Amazon のシステムは workflow based なアーキテクチャに向いている。我々はすでに「注文パイプライン」を持っている。現在は、注文の段階によって中央にあるデータベースのレコードが書き換えられるようにすることで実装している。これでは中央に負荷が集まり、スケールしない。これをスケールするようにするために、データや情報をノード間で受け渡し、パイプラインとして実装するようにする。
Workflow の問題は、そのデータを「どこに受け渡すか」をどうやって知るかだ。一つひとつのプロセスが、自分がどこにデータを受けたわすべきかを知っているべきだろうか、それとも、全体をコントロールする coordinator がいるのが良いだろうか。前者のケースは、エラー処理が難しいものの柔軟性に利点がある。これはクレジットカード決済処理などあらゆる場所から呼ばれる処理に向いている。ただ、大局から見ると DC (Data Coordinator) がいるモデルの方が利点が多い。特に、本の購入のように処理が固定化されているものに向いている。
いずれにせよ、現状の中央 DB の仕組みから分散 workflow の仕組みに変えていくことはいくつかの利点がある。まず、各コンポーネントがスケールしやすい。次に、 workflow 途中のシステムは DB へアクセスする必要がない。
ただ、難点もある。中央 DB であれば一瞬でデータを全体に反映させられるところを、分散 workflow であればデータの伝搬に時間がかかってしまう。 Workflow を組む際は、この変化が起こりうるということを意識して設計する必要がある。さらに、途中に Queue を挟む形式ではデータの変更は困難になる。これは分散 workflow では最初の設計が超重要ということでもある。
データは Workflow で渡されるような変遷するデータだけではなく、固定的なデータがあることも忘れてはならない。これらのほとんど変わらないデータを分散させるにはどうすれば良いだろうか?この場合、データのドメイン(領域)によって分割することが考えられる。 Amazon で言えば、ユーザ、販売店舗、それから商品カタログなどだ。このように分けることで、レプリケーションが実施でき、たとえばイギリスからドイツへとユーザが移動しても同じユーザ体験を実現することができる。このようにして、ユーザは 内部の仕組みやデータを気にせずに使えるようになる 。
おお。この「データの場所や内部の仕組みを考えずに使える」という考え方、 UX 感あっていい。さっきも出てきたやつ。
Applying the Concepts
上で議論したように、 DC processing は今回のコンセプトを実現できる。さて、その DC processing だが、大きく三つに分けられる。1つ目は DC processing 向きのもの、2つ目はデータの永続性が高いもの、3つ目はそのいずれにも当てはまらないものだ。3つ目のものは、通販処理の途中の状態変化が一例。 Queue と DB の中間的な存在なので、
aggregation queue
と呼ばれる。
Tracking State Changes
Workflow の途中で外からデータを変更する操作は、命令的だ。変更のためには pipeline のどこに操作があるのか把握できていなければならない。今回提案するのは、「今どこにいるか」を表すレコードを中央 DB に置くことだ。このデータは実際の注文中にのみ DB に存在し、終わったら分析 DB へと移動して本番 DB からは削除される。
突然の分析基盤。こんな前から販売分析行っていたということで、ここでも強さが実感できてしまう。
Making Changes to In-flight Workflow Elements
とはいえやはり、分散システムで状態を変えるのって難しいよね、というのが現実的に問題ということで、ここを掘り下げている。
Workflow model では、処理に必要な全てのデータを次のノードに渡す。 workflow の途中でデータを変えたくなったらどうすればいいだろうか?たとえば、本を注文後に出荷先のアドレスを変えたいような場合。今であればカスタマーサポートが中央DBをいじれば変更できるが、 workflow model ではそれはできない。ではどうするかというと、 Pub-Sub model を使うのが適切だ。各アプリケーションは、アドレス変更などのイベントを subscribe している。アドレス変更イベントを発行したとき、同時に中央 DB にステータス変更イベント行を追加する。イベントを処理できるプロセスがいた場合、その中央 DB にさらにステータス変更イベント行を追加する。このようにして、実際にイベントの変更を行い、さらにそれを依頼元に伝えることができる。
あるいは、 workflow coordinator が実際の処理を行っているノードに対して変更リクエストを行うことも考えられる。この処理も、 coordinator がアドレス変更イベントを subscribe すれば良い。
このような非同期のデータ変更だけでなく、同期的なデータ変更伝搬はどうだろうか。ユーザに同期的に結果を返すことができる点は嬉しいが、そのためには処理全体を同期的に行えるように作らなければならない。
つまり現実的ではないと。
Workflow and DC Customer Order Processing
論文のまとめ章。画像は引用の範囲におさまると思うものの、本家の規約について未確認なので、今回はペーパーを直接見にいってください。大丈夫そうと確認できたら画像として添付したいところ。
下図は、実際に今回の提案を適用したときの図だ。販売処理は中央 DB に保存されるのではなく、ノードからノードへとデータと共に移動していく。図から、 DB がデータドメインによって分割されていること、処理の途中に Queue が挟まることなどが見て取れると思う。それぞれの Queue は、それぞれのステータスに応じたインターフェイスを持っている。たとえば課金可能な注文は課金サービスの Queue に投入される。課金サービスは、課金サービスの Queue からジョブを取得・削除し、完了したら次のサービスに送信する(あるいは失敗したときは呼び出し元に返す)。
コメント
いやはや……めっちゃ面白いというか、時代背景を考えるといかに凄まじいことを実現しようとしていたかということですよね。 1998 年ですよ。 Windows 98 が出た頃。インターネットなんてそんな使われていなかった。この頃に SOA や API や MVC や Microservices や、その他色々な概念のベースとなる設計が、しかも実際の現場で出されていた。本当、凄まじいの一言です。
この論文、ざーっと自分が読んで意訳したものなので、色々と間違っているところもあると思います。もっと知りたいよと言う方は、ぜひ原文にあたってみて、ついでにこの記事の間違いも修正していってください。
それではみなさま、よいクリスマスを。