今回は、クラウド・アプリケーションのスケーリングに関する2回シリーズのパート2です。パート1では、水平スケーリング、垂直スケーリング、ステートレス・アプリケーションなど、スケーラビリティの概念について紹介しました。
この投稿では、アプリケーションの “線形 “スケーリングに近づくために使用できるテクニックについてお話します。
リニア・スケーリング:別名、虹の終わり!
もしあなたが完璧なアプリケーションを設計したなら、あなたのアプリケーションは “リニアに “スケールすることができます。素晴らしい!
待って、どういう意味?
線形スケーリングとは、アプリケーションに新しいリソースを x
個追加するごとに、y
個多くの負荷を処理できるようになることを意味します。
無表情
例を挙げましょう。Kubernetes上にデプロイされたウェブ・アプリケーションがあり、1つのドッカー・コンテナ(ウェブ・サービスのステートレス・インスタンスを実行)で毎秒100オペレーション(OPS)を処理できるとすると、理想的には、2つ目のドッカー・コンテナを追加して水平方向にスケーリングすれば、最大スループットは200OPSに向上します。コンテナ10個なら1,000 OPS、100個なら10,000 OPSといった具合です。
これがリニア・スケーリングの理想的な姿です!
しかし、現実の世界では、それが実現できる可能性は限りなく低いのです。なぜでしょうか?リニアスケーリングは虹の先にある金塊のようなものだからです。次のボトルネックが必ずあるからです!
コンテナ内で実行されるステートレスなウェブサービスがあり、それを上で説明したように水平方向に拡張できる場合、アプリケーションのコンポーネントはそれだけではない可能性が極めて高いのです。おそらく、コンテナがやり取りするデータベースやその他の中央永続ストアがあるはずです。そしてある時点で、コンテナの数が多すぎて最大容量で動作している場合、永続性ストアを圧倒してしまう可能性が高くなり、永続性ストアを拡張する方法を考えなければならなくなります。
ロードバランサーは別の例です。ロードバランサーにどれだけのリソースを割いているかにもよるが、背後にどれだけコンテナを置いても、もはやインバウンドのトラフィックを処理できないポイントに達するかもしれません。
上記のどのシナリオでも、リニア・スケーリングは実現できます!しばらくの間は。
システムには、現在のボトルネックとなっているコンポーネントが1つあるはずです。それを(通常は水平方向に)拡張する方法を見つけ、しばらくの間はリニアに拡張できるようになります。その後、システムの別の場所で別のボトルネックにぶつかり、ゲームは新たに始まります!まだ、虹の終わりには至っていないのです!
リニアなスケーリングを実現するための必須プラクティス(しばらくの間)
ステートレス・コンポーネント
システムのどの部分であれ、ステートレスで構築することができれば、スケーリングが容易になります。ウェブリクエストを処理し、データベースからデータを読み込み、それに対して計算を行い、レスポンスを返すようなシステムの部分があれば、それらは「ステートレス」の格好の候補となります。与えられたリクエストに対して、必要なすべての状態をデータベースから取得します。ローカルに状態を保持する必要はありません。リクエストの処理が終わると、状態を持ち越すことなく次のリクエストを処理する準備ができます。これは、水平にスケールするのが最も簡単なタイプのコンポーネントであり、Kubernetesのようなプラットフォームは、まさにこのタイプのコンポーネントのために作られました。
サーバーレス・コンポーネント
AWS LambdaやGoogle CloudRunなどのサーバーレス・コンピュート・サービスを使ってシステムの一部を構築できれば、トラフィックを処理するために必要なVMやコンテナの数を考える必要はなくなります。これらのサービスは、より多くのキャパシティが必要なとき、または余分なキャパシティを切り離すことができるときを自動的に検出し、それに応じて自分自身をスケールアップしたりスケールダウンしたりします!
ロードバランシング
システムのどの部分でも水平方向に拡張したいのであれば、ロードバランサーを導入する必要があるでしょう。ロードバランサーは入ってくるトラフィックをすべて受け入れて、アプリケーションのリソースにルーティングして仕事をさせる役割を担っています。ロードバランサーにさらにノードを追加すると、負荷が均等に分散され、スケーリングが可能になります。
Kubernetesのようなプラットフォームは、ロードバランシングのための組み込みソリューションを提供し、AWSのようなクラウド・プロバイダーも、機能豊富なロードバランシング・サービスを提供しています。
キャッシング
アプリケーションのスケーラビリティを向上させる最善の方法は、必要な作業量を減らす方法を見つけることです。キャッシュはこれを実現する素晴らしい方法です。
アプリケーションが複数回実行する必要がある計算は、キャッシュの候補になるかもしれません。計算を一度行い、その結果をキャッシュに保存し、再度計算を行うのではなくキャッシュのデータを再利用すれば、計算リソースを解放することができ、アプリケーションがより多くの負荷を処理できるようになります。
複数のテーブルからデータを結合し、実行に数秒かかるような高度なデータベースクエリがある場合、その結果をキャッシュし、複数のリクエストの処理に再利用することができれば、データベースへの負荷を劇的に減らし、アプリケーションのスケーラビリティを向上させることができます。
キャッシュには多くの選択肢がある:
・RedisやMemcachedのようなソフトウェアを使って、自分でキャッシュ・クラスタをセットアップすることができる。
・Redis CloudやAWS ElastiCacheなど、キャッシュクラスタを管理してくれるサービスを利用する。
・MomentoやAWS ElastiCache Serverlessのようなサーバーレス分散キャッシュを使うこともできる。
コンテンツ・デリバリー・ネットワーク(CDN)
Cloudflare、fast.ly、AWS CloudFrontなどのCDNは「エッジキャッシュ」を提供します。エッジキャッシュは、エンドユーザーのリクエストがアプリケーションに到達する前に、まず「エッジキャッシュ」、つまりリクエストの発信元から可能な限り地理的に近い場所にあるリージョナルキャッシュを経由するようにアプリケーションを構築することを可能にします。リクエストの処理に必要な値がエッジキャッシュで利用可能な場合、リクエストはアプリケーションに到達することなく処理されます。繰り返しになるが、アプリケーションをスケーラブルにするには、アプリケーションに必要な作業量を減らすことに勝る方法はありません!
エッジ・キャッシングは、多くのリクエストに繰り返し大量のデータを提供するアプリケーションで最もよく使用されます。Netflixのような動画ストリーミングサービスがその好例で、大きなバイナリ動画ファイルをエッジにキャッシュすることで、Netflixのコアサーバーの負荷を軽減することができます。
オートスケーリング
水平方向と垂直方向のスケーリングは素晴らしいが、どのような場合にそうなるのでしょうか?また、どのように?
アプリケーションのコンポーネントを水平方向に拡張できる優れた設計を思いついた場合、それを実行するタイミングを知る必要があります。オペレータがシステムに容量を追加するためのアクションを起こせるように、最大容量に近づいたときにアラートを出すメトリクスを作成したかもしれません。しかし、これは人間の介入に依存しており、エラーが発生しやすい可能性があります。
オートスケーリングは、最大容量に近づいていることを示す指標として主要メトリクスを設定し、容量追加のタイミングをシステムが自動的に検知する技術です。また、コスト削減のために規模を縮小しても安全なタイミングを検知することもできます。
これもKubernetesの設計で最重要視された機能で、自動スケーリングのための多くのオプションがすぐに利用できます。また、主要なクラウド・プロバイダーが提供する多くのサービスでも、自動スケーリング機能を見つけることができます。
データベースの最適化
データベースは多くの場合、アプリケーションの中で最もスケールが難しい部分です。リレーショナル・データベースに依存しているのであれば、例えばインデックスを作成するなど、ある種のクエリをどのように最適化できるかを理解することが重要です。クエリを最適化することで、スケーラビリティを劇的に改善することができます。ほとんどのデータベースは、クエリのパフォーマンスを監視するために使用できるツールを提供しており、多くの場合、最適化できる特定のクエリについて推奨を受けることもできます。
また、データをシャーディングまたはパーティショニングできるようにデータベース・スキーマを定義することが可能かどうかについても考える価値があります。たとえば、すべてのデータベースクエリが、ある月のレコードにのみアクセスする必要がある、または単一の顧客のレコードにのみアクセスする必要があることがわかっている場合、各パーティションを別々のサーバーで実行できるように、データベースをパーティショニングすることができます。これにより、データベースを垂直方向ではなく水平方向に拡張することができます。
サーバーレス・データベース
さらに良いのは、データベースのスケーリング問題を他の誰かに心配させることです。AWSのDynamoDBやAuroraのようなサーバーレスデータベースは、自動スケーリング機能を提供し、最も困難なスケーリング問題を解決してくれます。これらのサービスは、自社でデータベースを管理するよりもコストがかかるかもしれないが、メンテナンスやスケーリングの問題に対するエンジニアリングコストの節約は莫大なものになります。
コンテナ・オーケストレーション
コンテナ・オーケストレーション・プラットフォームは、このようなスケーリングの課題のために特別に設計されている。コンテナ・オーケストレーション・プラットフォームは、このようなスケーリングの課題のために特別に設計されたものです。コンテナ・オーケストレーション・プラットフォームは、箱から出してすぐに多くの機能を提供するため、コンテナの負荷分散やスケールアップ/ダウンをどうするかよりも、コンテナで何を実行するかについてほとんどの時間を費やすことができます。
Kubernetesのようなプラットフォームは、急な学習曲線を伴うことがあるが、非常に強力で、多くのスケーリング問題に対する独自のソリューションを考案する必要性からあなたを守ることができます。また、時代が進むにつれて、クラウドプロバイダー間でよりユビキタスになり、よりポータブルになりつつあります。
パフォーマンス指標を熱心に監視する
最後になりますが、間違いなく重要ではありません。スケーリングについて知っておく必要がある最も重要なことは、スケーリングの時期です。アプリケーションの健全性を示す適切なメトリクスと、これらのメトリクスを視覚化し、ユーザーが良い体験をしているかどうかを示す簡潔で理解しやすいダッシュボードがあることを確認してください。次のボトルネック(Next Bottleneck™)に近づいていることに早く気づけば気づくほど、ユーザーに影響が及ぶ前にスケーリングソリューションを見つける確率が高まります!
アプリケーションのスケーリングにおけるMomentoの役割
この記事のところどころで、スケーリングの問題を解決する最善の方法のひとつは、誰かに解決してもらうことだと話してきました。
DynamoDBのようなサーバーレスデータベースを使うことで、独自のデータベースクラスタを管理するのに比べて、スケーリングに関する様々な頭痛の種を減らすことができます。Kubernetesのようなプラットフォームを使えば、ロードバランシングや自動スケーリングを、自分で構築するよりもはるかに少ない労力で行うことができます。また、AWS Lambdaのようなサーバーレス・コンピュート・プラットフォームを使えば、コンピュート・リソースのスケーリングについて考える必要が全くなくなります。
Momentoサーバーレスキャッシュは、キャッシュのニーズを満たすために同様の役割を果たすことができます。Momentoを使えば、キャッシュを作成するだけで、どこからでもキャッシュへの読み書きを開始できます!リソースを管理する必要もなく、トラフィックパターンの変動に合わせてスケールアップやスケールダウンを心配する必要もありません。
サーバーレス・テクノロジーは、スケーリングの手間を省き、ビジネスを差別化することに集中できるようにします。次のアプリケーションを構築するとき、あるいは次のスケーリングの課題に取り組むとき、自分のニーズに合うサーバーレス製品があるかどうか、周囲を見渡すようにしてください!
Momentoでキャッシュを開始し、最も混雑する時間帯にアプリをオンラインに保ちましょう。