📖

re:Invent 2024: Serverlessスケーラビリティの実践 - 国際スポーツイベントの事例から

に公開
2024/12/10

はじめに

海外の様々な講演を日本語記事に書き起こすことで、隠れた良質な情報をもっと身近なものに。そんなコンセプトで進める本企画で今回取り上げるプレゼンテーションはこちら!

📖 AWS re:Invent 2024 - Serverless scalability unleashed (DEV319)

この動画では、大規模な国際スポーツイベントのServerlessバックエンド構築の経験を元に、Serverlessのスケーラビリティについて解説しています。Event-Drivenアーキテクチャを採用したLive Scoringシステムの設計から、RedisキャッシュやLambdaの同時実行数の制御まで、実際に起きた問題とその解決策を具体的に説明します。特に、CloudFrontキャッシュを無効化した際にRedisが過負荷状態に陥った事例から、スケーラビリティの境界の重要性や、Control PointとFlow Controlの必要性について詳しく解説。また、Performance Testingの重要性や、パターンをBlueprintに変換する際の考慮点など、Serverlessシステムを本番環境で確実に運用するための実践的な知見を共有しています。
https://www.youtube.com/watch?v=7Lxz6yoIzwA
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。
※ 画像をクリックすると、動画中の該当シーンに遷移します。

re:Invent 2024関連の書き起こし記事については、こちらのSpreadsheet に情報をまとめています。合わせてご確認ください!

本編

Serverlessのスケーラビリティ:プロジェクトの背景と課題

Thumbnail 0

みなさん、こんにちは。本日は貴重なお時間を割いてお越しいただき、誠にありがとうございます。まずはヘッドフォンの着用をお願いします。着用していないと、私の声が聞こえませんので。みなさん、準備はよろしいでしょうか?親指を立てていただけますか?素晴らしいですね。今日は「Serverlessのスケーラビリティを解き放つ」というテーマでお話しさせていただきます。これは、私が数年前にServerlessの開発を始めた頃の話から始まります。

Thumbnail 40

Thumbnail 70

AWS HeroのLee James Gilmoreの言葉を引用させていただきます:「始めるうえでの大きな利点の一つは、その簡単さにあります」。Serverlessは本当に素晴らしいものです。開発者として私たちは、シンプルなコードの単位で素早く開発を進められ、次々と機能を追加していくことができます。 ただし、そのうち多くのチームが混沌とした状態に陥ってしまうんですよね。うなずいている方もいらっしゃいますね - いわゆる「ビッグボールオブマッド」状態です。

Thumbnail 110

Thumbnail 120

本日お越しいただき、嬉しく思います。これから、私がMelbourneで開催された大規模な国際スポーツイベントのServerlessバックエンドを構築した際の物語をお話ししていきます。アーキテクチャやその他多くの要素について詳しくご説明させていただきます。このセッションを通じて、皆様が同じ過ちを繰り返すことなく、Serverlessのスケーラビリティを最大限に活用できるようなスキルと知識を持ち帰っていただければと思います。 これからは、このような状況をこのような状況に変えていきましょう。

Thumbnail 130

本日の内容はこちらです。まず、ライブスコアリングシステム、データフロー、イベント、そしてアーキテクチャについてお話しします。次に、このプロジェクト中に実際に起きた問題について掘り下げていきます。そして、大規模なServerlessシステムの制御について、アーキテクトとしてスケールを適切に管理し、計画通りに進めるために必要な事項を詳しく見ていきます。さらに、Serverlessパターンを本番環境に展開する方法についても触れます。Serverlessの開発は、単にコードを書き続けることではありません - 構造化された計画的なアプローチが必要です。今日は、アーキテクチャ、運用、計画など、Lambdaでスケーラブルなシステムを構築するために必要なすべての要素についてお話しします。最後に、皆様がServerlessのスケーラビリティを最大限に活用できるような実践的な情報をまとめて、締めくくりたいと思います。

Thumbnail 190

始める前に、私たちが扱うのはライブイベントなので、これはEvent-Drivenアーキテクチャということになります。これは私が初めて構築したシステムで、ここでServerlessの開発方法を学びました。約10週間という非常に短期間で構築し、その過程で多くのことを学ぶ必要がありました。初めての経験というのは最も学びが多いものですが、私にとってはここでServerlessについて最も多くのことを学んだと思います。これは、その日以降、私のすべての仕事の基礎となる知識となりました。今日は、そのすべてを皆様と共有させていただきます。

ライブスコアリングシステムのアーキテクチャと設計上の考慮点

Thumbnail 230

Thumbnail 260

Thumbnail 280

Thumbnail 290

Live Scoringシステムとイベントフローについて説明しましょう。Live Scoreの処理はイベント駆動型です。中心にScore Processing Systemがあり、Tournament Controlからスケジュール、ドラフト、選手名、試合のセットアップ、場所などの情報が、それぞれ異なるイベントとして入ってきます。 Chair Umpireからもイベントが来ます。これは実際にボタンを押す人たちのことで、ボタンを押すたびにイベントが発生します。人の手によって駆動されるシステムなので、設計する際には興味深い要素となります。 さらに、Statisticianもいます。これも同様に、コンピューターやラップトップを使って情報を入力する人たちで、様々な統計データがイベントとしてScore Processing Systemに送られてきます。 システムはこれらの情報を受け取り、Scoring Databaseに格納します。イベントはすべて人の手によって生成されるため、アーキテクチャを設計する際に考慮すべき重要な点となります。システムから生成されるイベントは信頼性が高く効率的ですが、人の手には間違いがつきものです。そのため、データベース設計には特に注意を払う必要がありました。例えば、Umpireが人間であるため、誤って違う選手にスコアを入力してしまう可能性があることを考慮し、重複イベントを受け入れられるようにシステムを設計しました。そのような場合、まずデータを処理して表示し、再度入力があった際に修正できるようにしています。

これらの人的要因に対応するため、データモデルの設計は冪等性を持ち、望ましくない副作用が発生しないようにする必要がありました。また、すべてのイベントがデータベース内で識別可能なレコードとして保存されるようにする必要がありました。

Thumbnail 360

サーバーシステムについて、多くの人が冪等性について話します。Lambda Powertoolsを使用している人なら、その中に冪等性のユーティリティがあることを知っているでしょう。ただし、これは厳密には冪等性というよりも重複排除に近いものです - アプローチの方法は様々です。既存のシステムに追加する形でPowertoolsのような強力なコードを使用することもできますし、 重複イベントを想定してシステムを設計し、データを破壊することなく更新可能で、再利用可能な形でデータベースに保存する方法を採用することもできます。

Thumbnail 380

Thumbnail 410

Score DB以外にも、世界中のブラウザーやユーザーに対応する必要があります。数百万のユーザーがDigital Experience APIを通じてアクセスしてきます。企業はこれをDigital Experienceと呼びたがりますが、実質的にはBFFパターン(Backend For Frontendパターン)です。このパターンを使用してデータベースと通信し、ブラウザーの初期状態に必要なスコア情報を取得します。ブラウザーやモバイルアプリケーションにおけるすべてのDigital Experience向けに、 リアルタイムの更新を行うWebSocketの通知コンポーネントが用意されています。

Thumbnail 450

試合を観戦している際、サーバーが変わるたびにテニスボールが選手間を移動するのが見えますが、これは私が作成したアルゴリズムなので少し誇りに思っています。すべてのライブ更新がこの方法で行われるため、フロントエンドはAPIを通じて初期状態を読み込み、その後の更新をリアルタイムで受け取ることができます。これによりAPIへの負荷を抑えることができ、非常に理にかなった設計となっています。もう一つの重要な要素は、上部にあるDigital Experience CMSです。これは 外部のWebシステムで、誰もがアクセスできるウェブサイトをホストし、トーナメントの今日の状況を確認したい人々にとって信頼できる情報源となっています。

スケーラビリティの課題:Redisキャッシュの過負荷事例

Thumbnail 470

Thumbnail 490

今日は中央部分の Score Processing と Digital Experience API に焦点を当てたいと思います。ここが今日お話しする内容の核心部分です。システムの構築プロセスを一緒に見ていき、アーキテクチャについて説明し、途中で行った判断についても触れていきます。そして最後に、重要なポイントをすべて確認します。ただし、覚えておいていただきたいのは、 このようなアプローチは避けたいということです。システムを構築する際は、ただ作り始めるのではいけません。

Serverlessを手にした多くの人は、すぐに構築を始めてしまいます。確かに、速くて簡単だからそうなってしまうのですが、システムをどのように分割するか、各コンポーネントをどう考えるか、そしてアーキテクチャに適合する様々なパターンについて、しっかりと考える必要があります。そうすることで、信頼性が高く、安全で、複数のソリューションに再利用可能なシステムを設計できるのです。これこそが私たちの目指すべきことです。Serverlessで組み立て可能なアーキテクチャの考え方が一度身につくと、もう後戻りはできません。自然と身についてしまい、素晴らしいものです。できることの可能性が大きく広がります。

Thumbnail 540

パターンを使って構築する際は、サブシステムの観点で考えます。この場合、Score Processing と Digital Experience API が明確なサブパターンとなっています。左側の Score Processing を見ていきましょう。パターンで重要なのは、Infrastructure as Codeとして分解することで、すぐにクラウドにデプロイできることです。AWSのコンソールは最近とても使いやすくなっています。多くの優れた機能強化がされています。Serverlessにおける Infrastructure as Codeは強い味方です。SST、Serverless Framework、CDK、CloudFormation など、あなたが使いやすいものを選べば良いでしょう。

Thumbnail 600

Score Processing はシンプルな Event Broker です。イベントが入ってくるので、これは典型的な Event Broker パターンです。 ここで「EventBridge がないじゃないか」と思われるかもしれません。この事例は EventBridge より前のものなので、それについては触れません。

これは別の Event Broker パターンです。API Gateway を通じてデータが入ってきて API にヒットし、そこでデータの検証が行われ、パケットが適切にフォーマットされているか、正しいソースからのデータかを確認します。その後、SNS に送られ、サブスクリプションを通じて SQS から Lambda プロセスへと流れていきます。これは素晴らしいパターンです。

このパターンには、ここで示す2つの異なる使い方があります。上部では Event Processing を行い、それを SQS に送っています。システムに入ってきたイベントの一部は、外部の CMS に送る必要がありました。これが、AWS のバックエンドサーバーシステムと別個の Web CMS を接続・統合した方法です。下部の Event Processor は、スコアデータベースにデータを送っています。スコア情報を収集して処理し、それらのレコードをソリューションの中心にある Aurora データベースに送り込んでいます。

Thumbnail 690

Thumbnail 700

右側には、処理を行うための Digital Experience API ブロックがあります。これも Aurora データベースと通信しています。開発を進めていく中で、機能の分離が必要だと気づき始めました。 右側からイベントが入ってきて、Digital Experience API にはさらに多くのトラフィックが入ってきます。つまり、アーキテクチャの両端から大量のトラフィックが流入し、中央の小さな Aurora データベースに集中しているわけです。 そこで決断を下しました。左側には Event Broker パターンがあり、右側には Digital Experience API があります。これは Serverless な API Gateway から Lambda につながる典型的な BFF パターンです。

中央にキャッシュの仕組み、つまり Redis を使用した ElastiCache によるライブスコアキャッシュを実装することにしました。Redis を選んだのは、素晴らしく高速だからです。10ミリ秒未満でデータを取り出せるのは本当に素晴らしいことです。Lambda がスケールしてこのような処理を行うのを見るのは、とても魅力的です。上部には典型的なスコアキャッシングサービスを構築しました。これは CloudWatch のタイマーで起動され、非常にゆっくりとした一定のペースで動作します。データベースからデータを読み取り、Digital CMS からデータを読み取り、さまざまな API 用のペイロードを全て Redis キャッシュにキャッシュしました。

Thumbnail 790

これにより、フロントエンドから大量の高速なリクエストが来ても、すぐにデータを提供できるようになりました。これがスコアやその他のデータの表示を高速化するために使用した仕組みです。このように、すべてが分離されています。Aurora データベースには1つのプロセスだけが書き込みを行います。Redis には多くのプロセスが読み取りを行いますが、書き込みを行うのは1つだけなので、望んでいた通り非常に安定しています。 グローバルなスポーツイベントのアーキテクチャとして、すべてのユーザーが API Gateway にアクセスするのは良くありません。時には、2,000万人もの人々が同じページにアクセスすることがあります。接戦の試合を見ている人々が、統計ページを更新したり、統計の更新情報を取得したりするわけです。

Thumbnail 820

このソリューションでは、API トラフィックの約80%を世界中のキャッシュから直接配信できました。これは素晴らしい成果です。残りの20%もかなりの量ですが、POP を経由して入ってくるため、影響は少なくなっています。アーキテクチャで必要だったもう一つの実装は、WebSocket を使用したライブ通知です。Cloudflare やキャッシュ、CDN があるため、システム内で実際に起きていることと、表示されることの間にタイムラグが生じるからです。

私たちはそれを念頭にシステムを設計しました。スポーツのライブイベント向けのシステムを設計・アーキテクトする際には、お客様にリアルタイムな体験を確実に提供する方法を考える必要があります。CDNキャッシュからのキャッシングを考慮に入れる必要がありました。私たちのAPIはCDNキャッシュの動作を制御するためのキャッシュヘッダーを返していました。いつでもAPIの動作を調整し、キャッシュヘッダーを変更して、キャッシュの制御方法を変更することができました。これは非常に重要なポイントです。多くの人はキャッシュを固定してしまい、後から制御できなくなってしまいます。スケールを考慮したシステムのアーキテクチャでは、制御性が非常に重要なのです。

Lambdaの制御不能なスケーリングと対処法

また、WebSocketを使用したWeb通知も設計しました。各通知で試合の直近3ポイントを送信するように設計しました。ユーザーのスコア情報が45-50秒程度遅れる可能性があると見積もっていたので、次のスコアが入った時点で必要な更新情報がすべて届くようにしました。Webサイトと通知で3〜4回の更新を行い、常にスコアが最新の状態になるようにしていました。

Thumbnail 940

サーバーシステムを構築する際には、テスト機能についても考慮する必要があります。パターンを作成してクラウドにプッシュしましたが、それをテストできる必要があります。このプロジェクトでは、ライブスポーツイベントのデータプロバイダーが米国を拠点としていました。トーナメントの再生は可能でしたが、時差の関係で非常に困難でした。そこで、このプロジェクトで最初に行ったのは、システムに入ってくるイベントをシミュレートするスコアシミュレーターの構築でした。サーバーシステムを構築する際には、最初の段階でテスト方法について考える必要があります。

実際にシミュレーターを作るまでは、コードを書きませんでした。APIを通じてイベントが発生した際に記録できる仕組みを組み込んで構築し、それをライブイベントで使用できるようにしました。これは素晴らしい機能でした。なぜなら、これらのイベントを本番以外のステージングやテスト用のQA環境にリダイレクトできたからです。問題が発生した場合や、データ入力者が予期せぬ操作をしてデータが異常な動きをした場合でも、本番環境以外で問題の切り分けを行い、対応することができました。

シミュレーションを行うことは、テストを推進する上で非常に重要です。素晴らしいのは、シミュレーションのスピードを調整できることです。テストの際、通常の10倍の速度でスコアの再生を行うことにしました。私たちの考えは、テストやQA環境でバックエンドが10倍の速度で動作し、フロントエンドも問題なく動作するなら、本番でも大丈夫だろうというものでした。その考えを貫き、このイベントに関しては良い判断だったと思います。

Thumbnail 1060

本番環境への移行方法や、システムの信頼性を確保する方法について考えてみましょう。その多くは計画に関することです。技術的な要素もありますが、必ずしもすべてが技術的なものではありません。今日、サーバーシステムのパフォーマンステストを実施している人はどのくらいいますか?おお、予想以上に多いですね。素晴らしいことです。多くの人はパフォーマンステストを行わず、急いで開発を進め、ドーパミンが放出され、興奮状態になります。「よし、このサービスは動いている、すごい、素晴らしい」と思います。そして本番環境に移行すると、少しおかしなことが起き始めます。

Thumbnail 1110

すべてが間違った方向に進んだとき - サービスが失敗するケースについて話すのが大好きです。なぜなら、そういったインシデントから学ぶことが多いからです。このプロジェクトでは、特定のインシデントを観察することで多くのことを学びました。最初のパフォーマンステストの際、テストを実行していたチームがCDNキャッシュを無効にすることを決めたのですが、私たちに知らせることはありませんでした。私にさえ知らせてくれなかったのです。何が起こり得るのか、まったく予想できませんでした。

Thumbnail 1150

パフォーマンステストは、ゆっくりと始まり、徐々に負荷を上げていきます。これは先ほどお見せしたDigital Experience APIアーキテクチャの主要部分を示した図です。ブラウザからのリクエストがCloudFront CDNキャッシュを通過します。キャッシュの有効期限が切れたり、トラフィックが増加するにつれて新しいPOPが立ち上がったりすると、一部のリクエストがAPI Gatewayにヒットします。Lambdaは、Redisからデータとスコアを取得するのに約10ミリ秒かかります。かなりの量のトラフィックを処理しており、おそらく1秒あたり10リクエスト程度を処理しています。

Thumbnail 1190

トラフィック量が増えると、Lambdaは自動的にスケールアップし、より多くのLambda関数が起動します。これがLambdaがスケールする際の動作です - AWSが説明している通りです。これがLambdaの自然な振る舞いであり、私たちはそれを気に入っています。だからこそ、Serverlessで構築するのです。

Thumbnail 1210

しかし、さらに多くのLambda接続が入ってきます。先ほどの段階では、Redisは少し負荷が高くなっていましたが、問題ありませんでした。このステージでは、パフォーマンステストの3/4程度まで進んだ時点で、システムは非常にうまく動作していました。すべてが順調に進んでおり、これは素晴らしいと考えていました。

Thumbnail 1230

Thumbnail 1250

その後、CloudFrontを取り除いたところ、すべてのトラフィックがAPI Gatewayに直接到達し、Lambdaがスケールを始めました。新しく立ち上がるLambda関数は、すべてコネクション指向のシステムであるRedisに接続していました。しかし、話はこれだけではありません。バックエンドでは、イベントも流れてきていました。私たちは10倍速で実行していたのです。ライブイベントを10倍速で実行するのは良いアイデアだと思っていたのですが、これもまたLambdaを経由してRedisにアクセスしていました。

Thumbnail 1270

Lambdaが至る所でスケールアップしていく様子を見ていました。この時点で、モニタリングのアラートが届き始めました。Lambdaが急激にスケールアップしているのを確認していた時、QAエンジニアが私を呼んで「Michael、スコアが逆戻りしているのに気付きました」と言ってきました。Redisを確認すると、過負荷状態でした。面白いことに、Serverlessシステムがこのように問題を起こしても、一見機能しているように見えます。AWS Lambdaは非常に回復力があるので、更新は依然として行われていたのです。

この時点で、私たちの小さなRedisインスタンスは、CloudFrontのキャッシュが取り除かれた状況に対応できるほどスケールされていませんでした。そのかわいそうなサーバーは新しい接続の処理に追われ、それらの新しい接続がメモリとCPUを消費し、オペレーティングシステムのファイルディスクリプタを使い果たすまで続き、最終的にロックアウトし始めました。今や、LambdaはRedisに接続しようとしても、できない状態になっていました。

スケーラブルなServerlessシステムの設計と制御

Thumbnail 1340

Thumbnail 1370

なぜこのようなことが起こるのでしょうか?アーキテクトとして、これはスケーラビリティの境界が存在するからです。スケーラビリティの境界はすべてのServerlessシステムに存在し、アーキテクトとしてシステムを設計する際にはそれを意識する必要があります。これらがLambdaが問題を起こす原因となり、赤い線で示されている部分は、高スケールのLambdaが低スケールのものと出会う場所を示しています。

Lambdaの問題について話すと、人々は循環ループの話をするのかと尋ねてきます。しかし、それだけではありません。この事例では、Redisキャッシュが問題でした。コネクション指向のものは全てスケーラビリティの境界となります。制限があるため、低ボリュームとして扱うことができます。アーキテクトとして、これらの制限、クォータ、利用可能なリソース、そしてどこまでスケールできるのかを理解する必要があります。これらは私たち全員が問うべき質問です。今回の場合、Redisキャッシュの十分なサイジングができていませんでしたが、確実に良い学びとなりました。

スケーラビリティの制限が発生する他の場所として、外部APIコールがあります。これはマイクロサービスで構築するものすべてにとってリスクとなります。私は自分のチームによく言うのですが、Lambdaから3つ以上の外部APIコールがある場合は、コードのリファクタリングを検討する必要があります。外部へのコールは全てリスクです。外部システムを呼び出すたびに、そのシステムがダウンしている可能性があります。たとえそれがあなたの管理下にあるマイクロサービスであっても、その回復力がどの程度かは分かりません。Werner Vogelsが数年前に言ったように、すべてのものが常に動作しているわけではありません。

Thumbnail 1470

スケーラビリティの制限が衝突する場合、LambdaがRedisキャッシュに接続する際、通常の操作での実行時間は短くなります。これは私たちが望む通りです - 非常に速く、6ミリ秒です。接続して、すぐに終了します。接続に1ミリ秒ほどかかり、その後データを読み込んでその接続を開いたままにします。6ミリ秒ごとに次々とデータを読み込んでいき、非常に高速です。しかし、このLambdaの実行時間が増加し始めると、影響が出てきます。AWS Lambdaでは、同時実行数に影響を与え、大規模な構築を行う際には、この同時実行数が最も注意を払うべき難しい要素となります。

Thumbnail 1510

この同時実行数は線形的に増加します。1秒あたりの平均リクエスト数が増えると、同時実行数も上がります。平均リクエスト実行時間が増加する場合、それにはさまざまな理由があり得ます。私は企業やエンタープライズのプロジェクトで、開発環境のLambdaをエンタープライズのセキュリティ要件によってVPCに配置せざるを得なかった経験があります。これは最近では問題ありません。VPC内のLambdaは今でも非常に高速です。

エンタープライズ環境では、他のネットワーク制御も導入されています。エンタープライズ環境で私が経験するのは、Lambdaの実行時間を3秒に設定してデプロイしても、非常に混雑しているエンタープライズ環境にデプロイすると、状況が変わってくることです。VPC内では何百万もの取引があり、多くのトラフィックが監視されフィルタリングされており、これらすべてが遅延とレイテンシーを追加し、時には実際のLambdaの実行時間が若干増加することがあります。異なる環境での実行時間がどこまで上がるかを把握し、それに応じて計画を立てる必要があります。

Thumbnail 1590

何かが上昇すると、同時実行数も上昇し、これはそのリージョンのアカウントのクォータによって制限されます。これを認識しておく必要があります。同時実行数が多くなりすぎると、同時に実行されているLambda関数が多すぎる場合にLambdaはスロットリングされます。AWS Lambdaのコントロールプレーンはこれ以上インスタンスを起動できなくなります。試みはしますが、それらの試みはすべて429拒否レスポンスを受け取り、これ以上Lambda関数を起動することはできなくなります。

Thumbnail 1650

もう1つの課題は、Lambdaの非同期呼び出しに関するものです。Lambda実行環境は、デフォルトで2回の再試行を行います。つまり、合計3回トランザクションの完了を試みるということです。これは耐久性と信頼性を高めますが、同時に繰り返し実行して接続を試みることで、さらなるストームを引き起こすことになります。 Lambdaがスロットリングを開始すると、1つの問題だけではなく、すべてのマイクロサービスで問題が発生します。このサブシステムだけでなく、アカウント内の他のすべてのサブシステムのLambda関数もスロットリングされてしまいます。

Thumbnail 1710

私は、誰かのミスでLambdaが制御不能に陥ったプロジェクトを経験したことがあります。プロジェクトマネージャーや技術チームが「チームに連絡して、アカウントの同時実行数を増やそう」と言うことがよくあります。 あるとき、アカウントの同時実行数を10,000に増やして問題を解決したと報告してきた人がいました。しかし、これは間違った対応です。追加された8,000の同時実行スロットもLambdaに消費され、すべてがスロットリングされたままだったため、スロットリングされた呼び出しに5倍のコストを費やすことになっただけでした。

Thumbnail 1770

本番システムで制御を取り戻すのは難しい作業です。 まず最初にすべきことは、設計上の制御ポイントを探すことです。スケールを考慮したアーキテクチャを設計する際は、チャネルやサブシステムの処理を停止できる場所を事前に考えておく必要があります。これは非常に重要です。なぜなら、制御不能にスケールしている状況では、何が制御不能になっているかを特定し、それを停止する必要があるからです。これが事態を収束させ、他のすべてを落ち着かせる唯一の方法なのです。

Thumbnail 1790

Lambda関数で何が問題になっているかを特定するには、最も高い同時実行数を探す必要があります。これが1つの手がかりになります。最も高い同時実行数を持つものが、おそらく問題の原因です。同様に、最も多くスロットリングされている関数も問題の原因である可能性が高いでしょう。これらのメトリクスのいずれかを使って、関数全体を検索、フィルタリングし、比較的素早く原因を突き止めることができます。

制御ポイントがない場合、利用可能な唯一の選択肢はトリガーを無効にすることです。これは必ずしも設計時に想定していない内部制御ポイントですが、AWS Lambdaにはこの機能が組み込まれています。Lambdaをトリガーする任意のトリガーを非アクティブにすることで、そのLambdaへのデータフローを停止できます。これにより、最終的にそのLambdaのスケールダウンが始まり、アカウントの同時実行数が回復し、他のすべてが正常に動作し始めるはずです。システムやアーキテクチャの内容によっては、リカバリーやオーバーフローの処理が必要になるかもしれません。これにより、システムを落ち着かせ、回復させ、前に進み、再び成功を収めることができます。

Thumbnail 1860

数スライド前のに戻りますが、先ほど私が話していた実行時間(Duration)についてです。私の個人的な意見ですが、AWS Lambdaで監視すべき最も重要なメトリクスは、先ほども申し上げた通り実行時間です。エンタープライズ環境や本番環境では、処理が遅くなりがちです。私はAWS Lambdaの実行時間メトリクスに対してCloudWatchの異常検知を使用することが大好きです。これは機械学習を使ってLambdaの実行パターンを理解し、1〜2標準偏差の変動があると警告を出してくれます。高低両方の偏差を検知してくれるので、通常より低いトラフィックの場合でも通知を受け取れ、下流のシステムに問題がある可能性を示唆してくれます。上昇傾向の場合は、スロットリングが始まる前に通知を受け取れます。これが重要なポイントです。私たちは観察し、その状況を理解できる必要があります。CloudWatchの異常検知は素晴らしく、作成するすべてのLambdaに対して有効にすべきだと思います。私は自分の作業のすべてでこれを実践しています。

Serverlessパターンの活用とBlueprintへの変換

Thumbnail 1940

Thumbnail 1960

では、Lambdaが制御不能なまでにスケールする様子を見てきました。ここで構築している architecture を見て、スケール時にどのようにサービスを制御すればよいのでしょうか?先ほど述べたように、Control Pointについてよく考える必要があります。Event Brokerパターンを確実に実装する必要があります。Control Pointとして SQS Queueを設置することで、Lambdaの処理を停止することができます。Lambdaが落ち着いている間、すべてのイベントはSQS Queueに確実にキャプチャされ、その間に問題を修正して素早くデプロイすることができます。これがLambdaの素晴らしい点です - 特定のユニットに対して作業を行い、応急的な修正を実装し、その後SQS Queueを再開することができます。

Thumbnail 1990

よく見落とされがちなのは、オン/オフを切り替えるControl Pointがある一方で、フロー制御についても考える必要があるということです。これはアーキテクチャ上の考慮事項です - このトークは本質的にアーキテクチャ的な思考についてのものです。システム内のフローの速度を制御するためにControl PointとFlow Controlを検討する必要があります。なぜなら、これがConcurrencyを上昇させることになるからです。数年前にリリースされたEvent Source Mappingコンポーネントには、呼び出すLambdaの最大Concurrencyを設定する機能があります。これらの数式を使って、TPSを計算し、Event Source Mappingのバッチサイズと最大Concurrencyを決定することができます。通信相手側のレートに合わせてフローを制御するようにEvent Source Mappingを設定できます。

アーキテクトとして、私たちはすべての非機能要件について考える必要があります。システムを通過する予想トランザクション数を理解する必要があります。システムを流れる予想ボリュームを理解していなければ、信頼性の高い方法でそれを処理するようにシステムを設定することはできません。私の経験では - 私の専門はシステム統合で25年間この仕事をしてきましたが - エンタープライズ統合プロジェクトに参加すると、予想されるボリュームを誰も把握していないことがよくあります。そんな状態でどうやって設計すればいいのでしょうか?ボリュームを把握することが重要です。今日の話から一つだけ持ち帰るものがあるとすれば、これ以上は叫びませんが、それです。

Thumbnail 2110

これらがシステムを構築する際に考慮すべき主なポイントです。私たちはArchitectureとSuccess のための設計について多く話してきました。また、最初の方で、システムをサブシステムに分解し、それらのサブシステムについて考え、それらを分離してパターンを作成し、Infrastructure as Codeを使用してそれらを体系化することについても話しました。これにより、私たちの行うすべてを繰り返し可能にすることができます。パターンを持っていれば、同じ問題領域の他の問題にそのパターンを適用でき、より迅速に進めることができます。パターンは本当に重要なのです。

Thumbnail 2170

Thumbnail 2190

開発者やAWS Heroの方々がパターンの重要性について話すのをよく耳にします。先日のJulian WoodさんとRain Eisenbergさんの講演を聞かれた方がいれば、パターンについて多く語られていたのを覚えているでしょう。 これらのパターンはserverlessland.comで見つけることができます。使用している技術に応じて検索し、パターンを見つけることができます。Serverlessland.comは一般的なパターンについて学ぶための素晴らしいリソースです。 また、AWS CDKについてはconstructs.devもあります。そこにはCDKですぐに使える構成要素が集められており、GitHubからダウンロードして自分のアカウントにデプロイすることができます。

Thumbnail 2210

この引用は、私がデザインし構築した製品の1つを担当するAccentureのServerlessチームリーダー、Manish Tejasからのものです。Serverlessは体験する必要があります。私も本当にそう信じています。Serverlessを実際に体験する必要があり、パターンや問題について話し合う時でも、私たちはよくインターネットで解決策を探します。この世界に独自の問題はなく、必ずどこかに解決策があるものです。しかし、私たちの経験から分かったのは、それらのパターンや問題、解決策は、あなたの特定のユースケースにおいて必ずしも同じように機能するとは限らないということです。

Thumbnail 2270

Serverlessの各ユースケースには微妙な違いがあります。システムパラメータやシステム内で起こっていることすべてに少しずつ違いがあるのです。そのため、パターンが期待通りに動作しない可能性があるので、特定のユースケースで本当に機能するかテストする必要があります。多くの人がパターンをダウンロードしてアカウントに読み込むだけですが、 私たちはBlueprintについて話す必要があります。単なる概念や一般的なやり方であるパターンを、Blueprintに変換する必要があるのです。

Thumbnail 2320

Thumbnail 2330

そのBlueprintは多くの要素を考慮する必要があります。この図はserverlessland.comから直接引用したもので、API GatewayからLambdaを経由してEventBridgeに至り、外部サービスと通信するLambdaへと発火する標準的なEvent Brokerパターンを示しています。今日私が共有した内容を踏まえると、スケーラビリティの境界があるため、いくつか不足している要素があることにお気づきでしょう。 アーキテクトとして、パターンやBlueprintを考え設計する際には、これらの要素を考慮する必要があります。 制御ポイントが必要です。なぜなら、システムがダウンした場合、トラフィックが流れ続け、多くの拒否や再試行が発生することになるからです。そうなると、サードパーティの外部サービスがダウンしたり遅くなったりしたために、制御不能なまでにスケールアップやスケールアウトが起こる可能性があります。

Thumbnail 2380

Lambdaの実行時間が再び増加しています。私の意見では、実行時間はLambdaの最大の敵だと思います。そのため、システムをオフにできる制御プレーンが必要です。また、フロー制御についても考える必要があります。システムが過負荷にならないようSQSを通じてフロー制御を設定する必要がありますが、そのためにはトランザクション量を把握する必要があります。レート制限を知る必要があります。そうすれば、システムが常に正しく動作するよう設定を計算することができます。 そして、DLQについても考える必要があります。処理できないものがある場合、システムを通過する他のイベントをブロックしないよう、それらを適切な場所に送る必要があります。これは非常に重要です。今日皆さんに持ち帰っていただきたいのは、確かにパターンは存在し、簡単で、そのままプロダクションにロードできますが、これらすべての要素について考える必要があるということです。これらは、あのRedisキャッシュとその周辺で何もかもが間違った時に学んだ核心的な教訓です。

これらは、そのプロジェクトから得た重要な基礎的な学びであり、現在も私のあらゆる仕事に活かされています。Dead Letter Queue (DLQ)の素晴らしい点は、問題が解決された後にそれらのイベントを再実行できることです。大規模に運用可能な信頼性の高いシステムを構築するアーキテクトとして、私たちはこれらの側面を設計に組み込む必要があります。

まとめ:Serverlessのスケーラビリティを解き放つ戦略

Thumbnail 2440

Thumbnail 2460

Thumbnail 2470

さて、Serverlessのスケーラビリティを解き放つということで、今日は多くのことをお話ししました。皆さんがServiceを使ったプロジェクトを進めていく中で、役立つ戦略をいくつか持ち帰っていただけたことを願っています。 AWS HeroのLee James Gilmoreの言葉を引用させていただきますと、 Serverlessの最大の欠点の1つは、始めるのが簡単である一方で、その容易さ自体が欠点にもなり得るということです。

Thumbnail 2480

Thumbnail 2490

Thumbnail 2500

Thumbnail 2510

Serverlessのスケーラビリティを解き放つためには、パターンを活用することを考える必要があります - パターンは素晴らしいものです。スケーラビリティの境界を見極める必要があります。 私たちの仕事の一環として、パターンをBlueprintに変換する必要があります。 そして、本番環境に移行する前にこれらの問題を発見できるよう、必ずPerformance Testingを実施する必要があります。もし今Performance Testingを行っていないのであれば、ぜひ始めるべきです。プレゼンテーション後に質問があれば、簡単な方法についてお話しさせていただきます。

Thumbnail 2530

これらすべてを慎重に行い、トランザクション量を理解し、適切な設定を行えば、皆さんのシステムも Serverlessのスケーラビリティを解き放つことができるでしょう。私はMichael Walmsleyで、AWS Heroとして、AccentureのGen Wizzerグループで顧客向けの社内プロダクトを開発しています。私はすべてをServerlessで構築しており、エンタープライズスケールでの開発を愛しています。

Thumbnail 2550

もっと詳しく知りたい方は、このQRコードから ServerlessDNA.comにアクセスしてください。これは私のブログプラットフォームで、今日お話しした内容やServerlessに関する他の話題について学ぶことができます。皆さんをこの旅にお招きできることを嬉しく思います。質問があればぜひ連絡してください。皆さんが直面している課題についてお聞きするのが大好きです。なぜなら、それが他の人々の学びにつながるからです。本日はご参加いただき、ありがとうございました。プレゼンテーションを楽しんでいただき、何か持ち帰っていただけたことを願っています。モバイルアプリでセッションのアンケートにご協力ください。皆さんからのフィードバックをお待ちしています。ご参加ありがとうございました。


※ こちらの記事は Amazon Bedrock を利用することで全て自動で作成しています。
※ 生成AI記事によるインターネット汚染の懸念を踏まえ、本記事ではセッション動画を情報量をほぼ変化させずに文字と画像に変換することで、できるだけオリジナルコンテンツそのものの価値を維持しつつ、多言語でのAccessibilityやGooglabilityを高められればと考えています。

Discussion