セッションのアジェンダ

加藤潤一氏(以下、加藤):それでは、私のセッションを始めたいと思います。アジェンダはこのようになっています。最初はリアクティブシステムと、それに関連してCQRS(Command Query Responsibility Segregation)とEvent Sourcingについて話したいと思います。アーキテクチャの刷新を計画していて、その新アーキテクチャの設計思想の中にこの2つの概念が関わってくるので、最初に話したいと思います。

CQRSとEvent Sourcingの採用理由

リアクティブシステムとCQRSとEvent Sourcingについて説明したいと思います。

次世代基盤のためのキーワードということで、この2つの概念を採用しました。アーキテクチャの結果の話をしてもあまりおもしろくないので、なぜ採用しているのかをメインに話したいと思います。

アーキテクチャ刷新の「Sagrada」というプロジェクトがあり、目標として2025年の事業計画があります。これに合わせて生産性を維持・向上できるプロダクトと組織を構築する目標があり、その手段の1つが「いつでもレスポンスを返せる状態になっていること」です。

すごく当たり前の目標を置いているわけですが、どんな状況でもレスポンスを返せる状態に持っていくのは、実は技術的にすごく難しいことです。それを実現するには、リアクティブシステムやCQRS、Event Sourcingの考え方。FalconというプロジェクトでもCQRSとEvent Sourcingの考え方を反映して運用してきていますが、引き続き踏襲してキープしていく考え方になります。

社会インフラを担うからこそ必要になる手段

「社会インフラを担うからこそ必要になる手段」という話もあったと思いますが、では社会インフラになっていくには、どんな状況であっても、サービスとして運営できるような状態を保っていかないといけないだろうと。そのために必要な技術は何かという話を技術チームの中で考え、戦略を組み立ててきた背景があります。

ところで「ユーザーの前でこういう言い訳できますか?」というのがあって。サーバやサービスが使えない状況になるのはよくあることですが、ユーザーの前で「よくあることですよ」とは口が裂けても言えない。「サーバ台数が足りなくて」とか、いろいろ言い訳はあると思いますが、それは提供者の理屈というところが大きいと思います。

使いたいときに使えないシステムは、利用者から見限られる。ビジネスチャットといえば、ほかにもいろいろあるわけで、競合を探せばいくらでも見つかる時代です。利用者が競合へ乗り換えるのは、比較的簡単にできる。使いたいときに使えるのはそれだけ当たり前であって、大きなインパクトを与えます。ではそこで「どういう考え方が必要か」が次です。

リアクティブシステムというのはそういう目的で使われるものですと。

“即応性”とは何か

どんな状況でも即応性を確保して、いつでも使えるシステムを実現する。即応性が何かというと、難しい言葉で表現されていますが、“状況に応じて素早く行動すること”や、“状況に当てはまること”などです。すごく簡単なことですが、たぶんエンジニアをやっていれば「そんなに簡単ではない」と頭の中でイメージできると思います。

記憶に新しい大障害で、2020年1月ぐらいに東京証券取引所で株式売買システムが全銘柄で売買不能になった話があります。NASというディスクがフェイルオーバーできなかったことが原因で、よく見たら人為的な問題が大きかったらしいですが、そのNASというディスク装置が故障することで、売買システム全体の機能を失ってしまった話があります。

これはいろいろなところでケーススタディなどがされていますが、東京証券取引所の戦略としては、恒久対策として「回復力を向上させること」が言われていて。異常を起こした部分を切り離して、障害から回復できるアーキテクチャを目指していくというもので、その手段の1つとしてマイクロサービスを掲げています。

ここでなにが言えるかというと、完全に障害を起こさない、止まらないシステムを目指すのではなく、障害から回復する能力を設計することに価値があるという話だと思います。

こういった“レジリエンス”という考え方が、Kubernetes、AWSも含め、インフラからアプリケーションで一気通貫してやっていこうという話は多いと思います。アプリケーションに関しても、レジリエンスはすごく重要になってきているという話だと思います。

ソフトウェアアーキテクチャのリアクティブシステム

レジリエンスというものがリアクティブの考え方の中にありますが、ちょっとインフラも含めて話をするとすごく規模が大きくなってしまうので、いったんソフトウェアアーキテクチャに絞って話を進めたいと思います。

“リアクティブシステム”は、AkkaやScalaを開発している会社で、Lightbend社がリアクティブというコンセプトを宣言した、「リアクティブ宣言」というものがあって。そこで掲げられている概念が4つぐらいあります。

“Responsive”というものがあり、最終的に届けたい価値は即応性だと。それを支える原理に“Elastic”や“Resilient”、伸縮性や耐障害性があります。

耐障害性は先ほど言ったような、回復力のある設計をやっていこうという話で、障害を起こさないのではなく、障害に直面しても異常な部分を切り離して正常な部分を保護して、異常な部分を正常に戻すということです。

Elasticは非同期・ノンブロッキングであったり。“位置透過性”は聞き慣れない言葉だと思いますが、非同期・ノンブロッキングはわりと聞きますよね。コンピューターリソースは分散されていたりしますが、位置透過性とは、その分散されている位置に関係なく扱えるという意味で、こういった概念が支える原理になります。

必要な手段があり、その大前提になるのが、「メッセージ駆動じゃないとそういったことを実現するのは難しいよ」と言われています。これが基本原理としてあります。

メッセージ駆動とはなにか

この概念はいろいろありますが、一番根底となる手段である、メッセージ駆動が何かと端的に話すと、リアクティブシステムは非同期・ノンブロッキングなメッセージ・パッシングによって、コンポーネント間の境界を確立します。メッセージ・パッシングが何かというと、メッセージのやりとりです。

ショッピングカートをイメージしてほしいんですが、右側がショッピングカートで、左側がそのカートを制御するクライアント。ここでそのステレオタイプみたいものが、メッセージを送受信するオブジェクトのActorになっています。

例えば、空のカートに何かアイテムを追加するときは「AddCartItem」というメッセージを送信します。タスクを依頼するので、そのためにメッセージを送信するというかたちです。コマンドを投げるみたいなイメージですね。コマンドを投げ、それが受理されると「成功した」、受理されなかったら「失敗しました」というメッセージが返ってきます。

これだけ見たら「メソッドをコールしているのとあまり変わらないよね」って話ですが、特徴的なのは、メッセージを投げても戻りは待ちません。タスクの完了を待たないことによって、クライアント側のCartClient側は別の仕事をできます。別の仕事がなかったらちょっと待ってたほうがいいのかもしれませんが、基本的には待たないので、Cart側が「成功したよ」と返すまではほかの仕事をやります。

要するに、スループットを最適化しやすい。ほかの仕事ができますから。ブロックされているわけじゃないので。というのが、「非同期・ノンブロッキング」という文脈でいうと、特徴的な部分です。

メッセージに反応するかどうかは受信のコンポーネント、Actorの状況次第です。処理する仕事がなければ、リソースはまったく消費しません。CartというActorは状態をもっていますが、AddCartItemのようなタスクがなければ、まったくCPUのリソースは食わない特徴をもっています。

先ほど位置透過性みたいな話をしましたが、左と右のActorが別々のノードにいても、原理上はメッセージが届くのであれば、リモートもローカルも関係ない話になってきます。そういったところが、位置透過性という部分です。

(次回につづく)