「キャッシュ」、そして「分散」
- 今一度
dev.to
のことを思い出してみよう
- 生成されたコンテンツを一定期間使いまわす
- キャッシュ; cache
- 広い意味でのキャッシュは様々なレイヤで行われ、場所、文脈、用途によって意味するものも変わる
- WebサーバがHTTPリクエストに対して応答する部分よりも外側に限れば、
一度生成・取得されたコンテンツを一定期間使いまわすこと
- 最もクライアントに近い部分ではWebブラウザ内部で、最も遠い部分ではサーバの内部実装で行われる
- クライアントに物理的に近い場所に存在するサーバに処理を担当させる
- Content Delivery Network, CDN
- 正式な供給源(origin)が発行したコンテンツを、一定の規則に基づいてキャッシュした上で、
物理的に近傍に位置するクライアントからの取得要求にoriginに代わって応答する
- エッジコンピューティング; edge computing
- CDNと比較してより複雑な処理や、ともすれば大量のデータを中央サーバに送信する必要があるような処理を、
クライアントの物理的近傍のサーバで済ませる。計算資源の分散、通信帯域の削減を可能にする
- 同等の処理を実行できるサーバが同時に複数存在する
- 最後の「同時に複数存在」するサーバだが、レイヤによって能力、前提が異なる
- 例えばCDNも、クライアントに物理的に近いエッジロケーション; edge locationには責務を担当可能なサーバは複数ある
- が、CDNの場合、エッジサーバ内部に必要なデータが存在しなければ、
originにリクエストを転送して一次情報の生成を要求し、それをキャッシュすれば良い
- 一方、originに該当するアプリケーションサーバ(群)はどうか
- ここが正式な一次処理を完遂できなければアプリケーション全体が立ち行かなくなる
- とはいえ、ただ1台のアプリケーションサーバや、ただ1台のDBだけでどれだけのユーザを捌けるだろうか
- 当然マシン性能にもよるが、2000年代前半にはC10k(10,000 connections/clients)問題として議論された
- 1台のマシン上で稼働するサーバで捌けるユーザ数には限界があるし、
- マシンの単体性能を上げる(垂直的, スケールアップ; scale-up)のにも限界があるし、
- どんなに性能が上がっても、急な負荷上昇やハードウェアの故障からは逃れられない
- 第一次的な、基幹となる処理担当部分にも、処理の 分散; distribution や、
ハードウェア的・ソフトウェア的 冗長化; redundancy による 可用性; availability の向上が求められ始める
- マシン単体性能を上げるのでなく、 マシンを増やす(水平的, スケールアウト; scale-out)ことで全体性能が上がると嬉しい
- スケールアウトしやすい(水平方向の スケーラビリティ; scalability に優れる)分散システムは、
サービスの成長や短期・長期の需要変動に伴うクライアント数の変動に対応しやすい
- RESTful で唱えられている ステートレス の理解が難しい、という話があったが、
この「分散の必要性」という文脈に乗ると少し納得がいくかもしれない
- 単一のサーバであればステートフルでも構わなかったのだが、複数のサーバで処理を分散担当するとなると、
「直前に担当していたサーバとクライアントとの間で保持していた状態が、別のサーバには共有されていない」
という問題が当然生じてきてしまう
- これをどうにかするためのアプローチとして、
- そもそもクラサバ間で逐一状態共有するようなことを避けて、処理の分散を容易にする
- RESTfulが重要視するところの ステートレス指向
- 状態を別の(高速に読み出しできる)DBなどに保存しておいて、どのアプリケーションサーバからも参照できるようにする
- かくしてWebアプリケーションのサーバサイド開発が、不可避的に 分散システム; distributed system 開発となる時代に
- これ自体もWebの登場以前から研究されてきた歴史がある。多くの技術・概念が登場し、一筋縄ではいかない
- 負荷分散; load-balancing
- 同様の責務を果たせるサーバが複数台存在するとき、それぞれの負荷が一様になるよう、
クライアントからのリクエストを適切に振り分けなければならない
- 合意形成アルゴリズム; consensus algorithms
- 複数のマシンが協働して(クラスタ; cluster)リソースの永続化とそれに対する操作を可能にするようなDBMSでは、
読み、書き、あるいはその両方を複数のマシンが担当できる、
または担当するマシンへの要求転送を行える、といった必要が出てくる
- 保管しているリソースそのものや、クラスタの状態理解がマシン間で 分岐; diverge してしまうとおかしなことになる
- クラスタに参加しているマシンは、最新の状態を、できるだけタイムラグなく、共有できなければならない
- ほかにもどんどん出てくるだろう