📖

re:Invent 2023: AmazonのPrime Dayから学ぶ輻輳崩壊の回避策

2023/11/28に公開

はじめに

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

📖 AWS re:Invent 2023 - Surviving overloads: How Amazon Prime Day avoids congestion collapse (NET402)

この動画では、Amazon Prime Dayの裏側で起こる輻輳崩壊の問題とその解決策を探ります。Jim RoskindとAnkit Chadhaが、高速道路の渋滞や母の日の電話混雑など身近な例を交えながら、システムの過負荷状態を分かりやすく解説します。Amazon CloudWatch、AWS WAF、Amazon SQSなどのAWSサービスを活用した具体的な対策や、クラッシュテストの重要性まで、大規模システムの安定運用に欠かせない知見が満載です。
https://www.youtube.com/watch?v=fOYOvp6X10g
※ 動画から自動生成した記事になります。誤字脱字や誤った内容が記載される可能性がありますので、正確な情報は動画本編をご覧ください。

本編

Jim RoskindとAnkit Chadhaによる「Surviving Overloads」の紹介

Thumbnail 0

こんにちは、ようこそ。多くの方が「Surviving Overloads」と、Amazon Prime Dayがどのように輻輳崩壊を回避しているかについて聞きに来てくださったと思います。もしそうでない方がいらっしゃいましたら、今が退出するのに良いタイミングです。私はJim Roskindで、Ankit Chadhaと一緒に発表させていただきます。私は.com側のDistinguished Engineerで、AnkitはAmazon Web Servicesのソリューションアーキテクトです。

Thumbnail 30

皆さんは、Jim Roskindとは一体誰なのかと思われるかもしれません。私はAmazon eCommerceに、コンピューティングコストを削減するために雇われました。.com側では多くのコンピューターを使用しており、それらをAWSからレンタルする必要があります。規模が大きくなるにつれて、それはコストの大きな部分を占めるようになります。私はAWSの人々に話をして、自分の仕事は彼らの製品をより少なく購入することだと伝えました。彼らは「それは素晴らしい。もし私たちが少なく購入する方法を見つけられれば、すべての顧客にも同じように教えよう」と言いました。そうすれば、彼らから購入していない人々も、ここで購入したいと言ってくるでしょう。これは非常に長期的な視点です。

私はまた、HTTP/3の基礎となるQUICプロトコルのアーキテクトでもあります。これはGoogleで働いていた時に行いました。Google Chromeでのメトリクスとパフォーマンス開発も主導しました。Chromeを使用中に「about:histograms」と入力すると、収集されている2000のメトリクスが表示されます。情報のアップロード方法はプライバシーに非常に配慮されています。一般的に、私はパフォーマンスを理解しています。また、オープンソース市場で約20年間使用されたPythonのProfilerも設計しました。

しかし、大きな問題は、コンピューティングコストを削減しようとする際、削減しすぎてブラウンアウトが起きないかと常に少し心配していることです。つまり、規模が不足する可能性があるのです。そのため、両者のバランスを取るのは繊細な作業です。この不安は問題に関するものであり、心配すべき大きな問題の一つが輻輳崩壊です。

Thumbnail 120

私がプレゼンテーションの前半を担当し、輻輳崩壊の実用的な例と理論について説明します。TCPの輻輳回避について聞くだけでなく、より広い意味で輻輳崩壊を理解していただくことを目指します。実は、これは私たちの周りに存在し、大きな問題となっています。パート2では、輻輳崩壊を回避するための実践的なAWSツールについて説明し、この部分はAnkit Chadhaが担当します。

輻輳崩壊(Congestion Collapse)の概要と実例

Thumbnail 150

私のセクションの概要は以下の通りです:congestion collapseとは何か、身の回りにある例、問題を回避する方法、問題の見つけ方、そして常に主張するテーマとして、コードレビューは信頼できないので過去の失敗をテストする必要があるということです。

Thumbnail 160

Thumbnail 180

最初の質問は、congestion collapseとは何かということです。これは非常に奇妙な現象です。システムがわずかでも過負荷になると、リソース使用率が100%になります。CPUかもしれませんし、ディスクかもしれませんし、ネットワークかもしれません。何かが過負荷になっているのです。 そうなると、キューが溜まり始めます。人々は遅れ始めます。そして驚くべきことに、生産的な作業がゼロになる地点に達します。すべてのマシンが100%で動いているのに、ユーザーは何の恩恵も受けていないのです。

Thumbnail 210

Thumbnail 220

congestion collapseについて最も重要なのは、この状態から抜け出せなくなることです。ワークロードが小さくなっているように見えても、抜け出せないのです。 これがどのように起こるのか、世界中の例から始めて最終的にPrime Day 2018で終わる5つの例を挙げていきます。高速道路のメーターライト、母の日の問題、TCPの輻輳、Webサーバーの過負荷、そして最後にPrime Day 2018について話します。

高速道路のメーターライトと輻輳崩壊

Thumbnail 270

まず、メーターライトについて話しましょう。高速道路でメーターライトを見たことがある人はどれくらいいますか?出口に向かうと、入口ランプがあって、赤と緑が交互に点滅し、緑信号で1台ずつ車を通すというものです。何をしているのか不思議に思うかもしれません。実は、単に交通の流れをスムーズにしようとしているだけではなく、すべてcongestion collapseに関連しているのです。

Thumbnail 290

メーターライトがない場合、どうなるでしょうか?密度が低く、車の平均速度が時速65マイルだとします。一定の線を何台の車が通過するでしょうか?高速道路を横切る線を引いて、車、車、車、車、車とカウントしてみましょう。

Thumbnail 320

Thumbnail 350

それがスループットです。道路は私たちのために機能しています。実際に交通を運んでいるのは素晴らしいことです。しかし、渋滞し始めるとどうなるでしょうか?高密度の状況を考えてみましょう。あなたと前の車との間隔が1インチしかない場合、どのくらいの速度で運転しますか?聴衆の中の誰かが正直に「止まります」と言います。その通りです。時速0マイルで走行することになります。では、ここで高速道路に線を引いたら、どれくらいのスループットが得られるでしょうか?答えは、完全に停止状態です。あなたもこのような渋滞に巻き込まれたことがあるでしょう。スループットがゼロの状態です。なぜ高速道路を作ったのかと疑問に思うほどです。交通を運べていないのです。

Thumbnail 360

Thumbnail 370

Thumbnail 380

Thumbnail 390

ここで何が起きているのでしょうか?最も明らかなのは、高速道路が生産的な仕事を全くしていないということです。では、これはどのように起こるのでしょうか?もう少し深く掘り下げてみましょう。通常、ドライバーは交通が流れているときに高速道路に乗ります。高速道路に乗り、少し走行して、降りる。これは良い一日に聞こえます。しかし残念ながら、高密度の状況では、彼らは渋滞の中で何時間も資源(高速道路)を使用することになります。興味深い気づきは、彼らが高密度状態を維持し、交通の流れを妨げているということです。そのため、渋滞が発生し、それによって彼らの速度が遅くなります。速度が遅くなると、高速道路の使用時間が長くなり、さらに渋滞を引き起こします。これは死のスパイラルです。渋滞崩壊は非常に状態依存的で、抜け出すことさえできません。

Thumbnail 410

Thumbnail 430

Thumbnail 440

一度この渋滞が発生すると、回復には何時間もかかります。実際、渋滞に巻き込まれていても、何マイルも先で原因となった障害が解消されているのに、まだ渋滞した高速道路に閉じ込められていることがよくあります。これが高速道路での死のスパイラルの結果です。メーターライトはどのように役立つのでしょうか?メーターライトは、交通密度を損なうことなく、路肩で待機させる効果があります。密度が高くなりすぎると、交通は遅くなります。許可が出たら高速道路に乗り、走行して降りる。これにより、交通の流れが維持されます。ここで、渋滞崩壊を避けるために実際にどのようにメーター制御が行われているかが分かり始めます。高速道路に乗るために信号で立ち往生しているのは問題ではありません。彼らは高速道路がそのような状態になることを望んでいないのです。

電話ネットワークにおける「母の日現象」と輻輳崩壊

Thumbnail 460

Thumbnail 470

Thumbnail 480

しかし、一度渋滞崩壊が起こると、死のスパイラルは状態を記憶します。そして、交通需要が減少しても、あなたはまだ大きな渋滞に巻き込まれたままです。回復には何時間もかかります。渋滞した高速道路利用者は過剰に使用し、回復を遅らせます。さて、これが高速道路の話です。電子のように「もっと速く移動する」と言えますか?はい、これは母の日の問題です。私がBell Labsで働いていたとき、「母の日現象」とも呼ばれていました。Bell Labsは全国の電話ネットワークのアーキテクチャを心配していました。

この青い線はAT&Tの長距離回線を表しています。そして母の日です。西海岸の学生が母親に電話をかけようと決心します。とても理にかなっています。母の日に母親に電話をかける人は誰でしょうか?多くの人がそうするようですね。さて、この学生は試してみます。まず、電話を取ります。これは昔ながらの電話です。皆さんの中には、受話器を取って発信音を待つ必要があった時代を覚えている人もいるでしょう。発信音は、地域の交換局から外線接続を行うための専用回線が確保されたことを示していました。今、彼女は発信音を待っています。その小さな...まだですね。そして最終的に、発信音が聞こえます。素晴らしい、許可が出ました。交換局から長距離回線に向かう専用の外線が確保されたのです。

番号をダイヤルすると、長距離回線がそれを検知し、バーンと全国に接続して回線を確保します。問題ありません。そして、お母さんの近くの交換局に到達しようとする地点まで来ます。そこで何が起こるでしょうか?バーン。申し訳ありませんが、お母さんの交換局に入る回線が利用できません。それほど悪くは聞こえませんね。いつもそうなるわけではありません。しかし、問題は発信者が状況を誤解してしまうことです。発信者はギークだけが知っているようなものを聞くからです。「rapid busy」と呼ばれるものを聞くのです。「エー、エー、エー、エー」というような音です。残念ながら、ギークでない人は、お母さんが電話中だと思ってしまいます。ビジー信号が聞こえたから。お母さんが今、家で電話中に違いない。お母さんは一日中出たり入ったりしています。今すぐもう一度かけ直さなければ。これが唯一のチャンスかもしれない。多分、兄弟か姉妹が今お母さんと話しているんだろうから。

Thumbnail 610

Thumbnail 620

これがいかに問題かがお分かりいただけると思います。ネットワークはダイヤルトーンを待つことで飽和状態になり、エンドツーエンドの接続がゼロ、収益もゼロ、そして利用率は100%になってしまいます。すべての交換局でキャパシティを最大限に使用していますが、電話システム上で生産的な作業は何も行われていません。悪いニュースは、「ビジー」が実際には話中ではなく、システムが負荷を受けていることを意味していたにもかかわらず、回線が話中だと人々に伝えることで、再ダイヤルを促してしまったことです。

Thumbnail 640

ある時点で、電話会社はこれに気づき、皆さんも聞いたことがあるかもしれない方法に変更しました。「申し訳ありませんが、現在すべての回線が混み合っています。後ほどおかけ直しください」という録音メッセージです。「お母さんは電話中ではありません」と付け加えることもできたでしょうが、そこまでは考えませんでした。これはかなりうまくいきました。人々は「ああ、お母さんは電話中ではないんだ。まだランダムなタイミングだから、1時間後にかけ直そう」と考えるようになりました。混雑を通知することで、発信者の行動を完全に変え、このサイクルから抜け出すのに役立ちました。

TCPの輻輳と Van Jacobsonによる解決策

Thumbnail 670

では、TCPの輻輳について見てみましょう。TCPのようなパケット交換ネットワークでは、パケットを送信します。送信ウィンドウと呼ばれるものがあり、これは約16パケットくらいです。これらを未確認のまま残し、受信確認を待ってから、さらに送信します。つまり、常に16パケットが飛んでいる状態で、この数は少し増減することがあります。TCPについては、この講演で扱える範囲をはるかに超える複雑さがあるので、深く掘り下げることはしません。

Thumbnail 700

ルーターには多くの入力と出力があります。確率過程では、時として一方の側から大量のパケットが入ってきて、それらが全て1つの出力リンクに向かうことがあります。そんな時、ルーターはどうすればいいのでしょうか?コンピューターサイエンスを学んだ人なら、キューを使うと答えるでしょう。しかし、電気工学を学んだ人なら、有限のキューがあることも知っているはずです。キューがオーバーフローすると、パケットは破棄されます。インターネットは、パケットを平等に破壊する機会を与えると言えるでしょう。

Thumbnail 750

Thumbnail 760

これが輻輳を示唆する方法です。キューが溜まってルーターのメモリーが足りなくなると、 受信側が「パケット4がまだ届いていません。もう一度送ってもらえますか?」と言うかもしれません。これは親切な要求に聞こえますが、輻輳時には、パケットが直接通過するよりも多くのネットワークリソースを使用する可能性があります。システムが混雑するにつれて、パケットの再送が始まり、より多くのリソースを使用することになります。これは、高速道路で起こることと似ています。

Thumbnail 810

Thumbnail 830

この問題の解決策は難しいものでした。Van Jacobsonという非常に賢い人物が、これが困難な問題であることを認識し、解決策を見出しました。私は彼をインターネットの救世主だと考えています。これは、インターネットがほぼ崩壊しそうになった昔の出来事です。 重要なのは、輻輳に遭遇した各接続の送信ウィンドウを約50%縮小したことです。送信レートを約半分に減らそうとしたのです。興味深いのは、これにより集約フロー、つまり送信される総フローの指数関数的なバックオフが達成されたことです。このアプローチがインターネットを救ったのです。

Webアプリケーションにおける輻輳崩壊のメカニズム

Thumbnail 870

では、多くの皆さんがより身近に感じるであろう、Webアプリケーションの構築について考えてみましょう。 Webアプリケーションが過負荷になる状況を想像してください。アプリケーションが1秒間に100トランザクションを処理できると仮定します。1秒間に110トランザクションを受け取った場合、何が起こるでしょうか?コンピューターサイエンスを学んだ人なら、入力が出力より速い場合どうするか知っていますね。キューを使います。しかし、1秒間に110トランザクションだと、キューは増加します。キューが増加すると、ユーザーは何を感じるでしょうか?遅延です。小さなスピニングアイコンが表示されます。つまり、キューが溜まっていくのです。

Thumbnail 910

Thumbnail 920

Thumbnail 930

全員がサービスを受けられますが、完全ではありません。ユーザーは何をするでしょうか?10秒経っても応答がない場合、あなたは何をしますか? リフレッシュボタンを押しますよね。驚くべきことではありません。リフレッシュボタンを押すと、何が起こったでしょうか?サーバーに輻輳が発生し、ユーザーがリフレッシュボタンを押しました。 そして今、実効的な需要が増加しました。元々は本当に1秒間に110トランザクションだけだったことを思い出してください。ユーザーは「自分のシステムの問題かもしれない、ISPの問題かもしれない。わからないけど、とりあえずリトライしよう」と考えます。そして実効的な需要は220にジャンプします。1秒前はたった10%オーバーだったのに、今では予想していた処理能力の100%以上オーバーになってしまったのです。

Thumbnail 970

Thumbnail 980

死のスパイラルが始まりました。Webアプリケーションが過負荷状態です。Webサーバーが1秒あたり100トランザクションを処理できると仮定しましょう。しかし、実際の需要は220になっています。何が起こるでしょうか?キューの遅延が急速に増大していきます。それ自体が原因となって、さらに悪化していくのです。これは輻輳崩壊の悪循環です。3回以上リロードすると、440にまで膨れ上がります。このキューは巨大になってしまいました。悪いことに、通常サーバーは「次のリクエストを処理しよう。製品の詳細ページが欲しいのか。ここで組み立てよう。はい、できた。あれ?接続が切れてしまった。次は何だ?ホームページが欲しい?簡単だ。はい、できた。え?また接続が切れた」というような動作をします。実際に有効な作業はどれくらい行われているでしょうか?全く行われていません。サーバーは100%稼働していますか?間違いなくそうです。システムは100%稼働していますが、有効な作業は0%です。システムは自己増殖的に悪化し、ユーザーにさらなる過負荷を促してしまいます。そしてこの状況から抜け出すことができません。

Thumbnail 1020

Thumbnail 1030

FIFOリクエスト処理、つまり先入れ先出し方式では、リクエスト元は応答が構築される前に接続を切ってしまいます。有効な作業は全く行われません。そこで、負荷を制限してみましょう。「負荷の見積もりを数パーセントしか間違えなかったのに、100%まで上がってしまった」と言います。あるテレビ番組で言うように、「What Could Possibly Go Wrong?(一体何が悪くなるというんだ?)」です。この番組を見たことがある人はいますか?ええ、そうですね。アメリカで見られる文化的な現象かもしれません。とにかく、負荷を制限するとします。上流の受信側に「到着したパケットの半分を捨てろ」と言います。「それはかなり過激だ」と思うかもしれません。「100トランザクション用にスケールしたのに。200になるはずがない」と。しかし悪いことに、すでに440まで押し上げられています。パケットの半分を破棄しても、実際に処理するのは220です。

Thumbnail 1070

Thumbnail 1080

Thumbnail 1100

キューはまだ成長し続けています。負荷の50%を制限しているのに、キューは依然として増大しています。ほとんどのユーザーはリロードを試みた後、最終的にはサイトを離れてしまいます。50%の制限をしても220が許可されてしまい、キューは増大し続け、崩壊も続きます。死のスパイラルは状態を持つ死です。アプリケーションは行き詰まっています。これは奇妙な現象ですが、100%になったときに何が起こっていたかを説明し始めていますか?ええ、少なくとも何人かがうなずいていますね。元に戻す必要があります。さて、回復を簡単にする方法があります。よくあるトリックですが、実は面白いものです。IT担当者は「誰かが無限ループを入れたんだ。もううんざりだ。全マシンをバウンスしよう」と言います。バウンスとは、再起動の専門用語です。

サービス指向アーキテクチャにおける輻輳崩壊の連鎖

Thumbnail 1120

Thumbnail 1140

Thumbnail 1150

そして、これが偶然にも全てのキューをフラッシュします。良いニュースは、キューをフラッシュすると、この時点で多くのユーザーがあなたのサイトをあきらめているということです。そのため、実際の需要はおそらくわずか50程度です。ただし、4倍に増幅されているので、200のように感じられます。しかし、新しい応答を作成して提供し、実際に生産的な作業を行い、ユーザーが満足している場合、ユーザーがまだそこにいる間に応答する必要があります。輻輳崩壊時に次の保留中のリクエストに応答することは無意味です。一度そこに陥ると、抜け出せなくなります。では、なぜユーザーのバックオフだけでは常に私たちを救ってくれないのでしょうか?ユーザーが離れていくにつれて、最終的にはサイトがダウンしているという噂が広まり、状況が改善されると思うかもしれません。

Thumbnail 1170

しかし、多くの人々がサービス指向アーキテクチャを使用しており、これには複数のレイヤーが含まれています。ユーザーがService-1を呼び出し、それがService-2を呼び出し、さらにService-3を呼び出し、最終的にデータベースとして機能します。データベースが過負荷になったとしましょう。データベースが過負荷になると、レイテンシーが増加し始め、Server-3は「時間がかかりすぎた、何か問題が発生したに違いない」と判断します。そして当然、リトライを行い、さらに過負荷になります。そのため、両方が失敗し、今度はServer-2がService-3に、Service-3がService-2に失敗します。そして「これは何かの偶然の事故に違いない。コンピューターが切り替わったのだろう。こういうことは時々起こる。私がすべきことは分かっている。私がすべきことは...」ここで皆さん、一緒に言ってください。「リトライ」です。少なくとも何人かの方は言えましたね。私はまだ舞台での振る舞いを磨いている最中です。

しかし、ここで各サービスが1回ずつリトライを行うと、トラフィックが倍増することがわかります。Service-3とデータベース間で2倍、Service-2とService-3間で2倍、Service-1とService-2間で2倍になります。ユーザーにリトライを要求する必要さえありませんでした。この小さな図では、1回のリトライで、データベースは本来想定されていた負荷の8倍の実効負荷を受けることになります。

Thumbnail 1250

Thumbnail 1270

これには上限がないことを理解する必要があります。1回のリトライでさえ、まだ問題があります。 ちなみに、5回よりはずっとマシです。私が知っているシステムでは、各レベルで5回のリトライを行っていて、5、25、625倍の負荷が基盤となるデータベースにかかっていました。これは決して良いものではありません。625倍も増幅されると、実際の負荷がそれほど大きくなくても大変なことになります。 2桁の倍率ですね。これで、Prime Day 2018の話に移りましょう。

Amazon Prime Day 2018の輻輳崩壊事例と教訓

私たちは分散ハッシュテーブルを使用していました。分散ハッシュテーブルは、名前を与えると値を返すものと考えられます。名前は製品名や製品番号かもしれませんし、値は製品に関するさまざまな情報かもしれません。分散ハッシュテーブルでは、辞書のセクションを異なるものに分割します。リクエストが来ると、ルーターがどのデータベースに答えがあるかを決定し、そこに行って検索し、答えを返します。

Thumbnail 1310

残念なことに、いや、実際には幸運なことに、Prime Dayには面白いセールがあります。今日がCyber Mondayなので、一部の人々の頭にあるかもしれませんね。 時には本当に良いセールがあり、「ホットキー」と呼ばれる現象が発生することがあります。これは、多くの人々が特定の製品について問い合わせることを意味します。そうすると、その特定の製品に関する多くのトラフィックが集中します。分散ハッシュテーブルの下端では、ランダム性から期待していたような良い分散が得られません。これが起こると、ホットパーティションが過負荷になり、タイムアウトしてしまいます。

Thumbnail 1360

上位のシステムがリトライを開始し、リトライストームが始まりました。Amazon.comには、公式に約5回のリトライを試みるシステムがいくつかありました。3つか4つ以上のレベルがあったと思いますが、かなり印象的でした。残念ながら、レイテンシーの障害がリトライストームを引き起こし、約3時間後にダウンしてしまいました。 最終的に私たちを苦しめたのは、隠れたキューでした。人々が存在すら知らなかったキューです。コードレビューをしていても、皆さんのほとんどがその存在に気づかないでしょう。

これは、コードレビューを行い、隠れたキューを見つけることがいかに難しいかを示しています。実は、TCP受信バッファが下のデータベースで1メガに設定されていました。私たちはHTTP Keep Aliveと呼ばれる方法を使用していて、1つのTCP接続を再利用して複数のリクエストをパイプライン化していました。各リクエストは約1000バイトでした。1メガあったので、これらのTCPラインのそれぞれが、すべてのサーバーからこのホットサーバーへ1000リクエストを、誰にも見えないようにキューに入れていたのです。私たちは偶然にも、底辺に途方もなく大きなキューを持っていたのです。でも、受信バッファがキューだと誰が疑ったでしょうか?

Thumbnail 1450

Thumbnail 1460

そして、これが本当に爆発的に広がっているのがわかります。2018年のことについて読むことができます。Amazonは約3時間ダウンしました。私たちがこれらの問題のいくつかを修正するために、大幅にスロットリングをかけ、速度を落とし、パッチをリリースするのに、それだけの時間がかかりました。最終的に状況をコントロールできるようになりましたが、生産的な仕事は何もできていませんでした。そしてそれはPrime Dayだったので、上層部の重要人物たちが注目していました。それは良くないことでした。 そこで、変更が加えられました。まず、輻輳に関する綿密なレビューとテストが行われ、特にリトライに焦点が当てられました。私たちはそれをほぼ瞬時に抑えました。 リクエストごとのリトライは1回以下に制限されました。良いニュースは、誰かにコードを5回のリトライから1回のリトライに変更してもらうことは、おそらくバグを引き起こさないということです。1文字を変更するだけです。非常にシンプルな変更です。

Thumbnail 1480

しかし、目標は漸近的にリトライをゼロにすることです。 その方法は、特定のサービスで、時にはホスト全体で、下位レベルのサービスから成功応答を得た回数を集計することです。100回の成功応答を得るまで、自分のレベルでリトライをオフにし始めます。これで、リトライの予算が2倍ではなく、100分の1程度になります。つまり、増幅係数が1.01ではなく0.01倍になるのです。

私たちは厳しく要求し、より大きな変更に進むにつれて、それを押し下げました。大規模で無制限のキューに制限を設け、多くのキューを見つけ、それらをクリーンアップし、有限のサイズに縮小しました。しかし、私たちはもっと良く知っていました。すべてを見つけることはできないと分かっていたのです。そこで、クラッシュテストの要件を設けました。クラッシュテストとは、これらのサービスごとに、スケールした限界を超えて負荷をかけることを意味します。そして、レイテンシーが増加するかどうかを観察します。レイテンシーが増加すれば、そこに隠れたキューがあることを意味します。それがレイテンシーを増加させているのに、気づいていなかったのです。

過負荷への対処と効率的なシステム設計の重要性

Thumbnail 1550

このクラッシュテストがそれを明らかにします。私が取り組んでいたこの全ミッションが、可用性と効率性に関するものだったことを理解してください。誰もが「トラフィックが増えると思ったら、安全のためにスケールアップすべきだ」と言いがちです。そして、お金の話をする人は「使っていないコンピューターにお金を無駄遣いするな、スケールダウンしろ」と言います。そこには常にプレッシャーがあり、効率性のためには容量を最小限に抑える必要がありますが、ランダムなトラフィックの変動や過負荷は起こりうるのです。

Thumbnail 1580

これからより詳しく説明しますが、やるべきことがいくつかあります。ランダムな過負荷をより適切に処理する必要があります。後ほど詳しく説明しますが、輻輳崩壊を回避する方法を見つける必要があります。過剰利用に対しては、段階的な機能低下が必要です。一部のリクエストを失敗させる覚悟が必要です。実際、マーケティング担当者にこう説明するのがいいでしょう。「プログラマーとして2つの選択肢があります。誰にもサービスを提供しないか、一部の人にサービスを提供するか、どちらがいいですか?」と。彼らが「FIFOキューで待機して全員にサービスを提供すればいいじゃないか」と言ったら、「聞いていなかったかもしれませんが、全員にサービスを提供しようとすると、誰にもサービスを提供できなくなります。失敗する覚悟が必要なんです。最小限の作業で素早く、優雅に失敗しなければなりません」と答えます。

Thumbnail 1630

では、輻輳崩壊を回避する方法について話しましょう。過負荷と共存することに関して、考慮すべき3つの大きなポイントがあります。サービスを構築する際、最悪のことは実際に人気が出てしまうことだと言う人もいます。突然、多くのものを抱えることになります。よくあるのは、Slashdot効果で10倍の負荷がかかることです。「そんなの準備できていませんでした」となるわけです。過負荷は起こり得るし、実際に起こります。リトライには注意が必要で、過負荷時にはより効率的になる必要があります。これはさらに複雑で興味深いことですが、これら3つのポイントについて詳しく見ていきましょう。

Thumbnail 1660

Thumbnail 1680

まず第一に、過負荷は起こります。呼び出し元が過負荷状態を判断できなければ、リトライするかどうかを決められません。そのため、エラーメッセージで返される情報を増やすことが重要です。過負荷を明示的に示す必要があります。電話会社がそうしているのを見ましたね。 過負荷にはサービスの低下が必要だということを理解してください。常に全員にサービスを提供することはできません。それは不可能です。過負荷なのですから。崩壊のスパイラルに陥るよりも、リクエストを失敗させたりスロットリングしたりする覚悟が必要です。

Thumbnail 1690

第三に、過負荷を助長しないことです。特にタイムアウトに対するリトライには十分注意してください。リトライストームは壊滅的な影響を与える可能性があります。リトライを1回未満に制限しますが、最低でも1回にしてください。ちなみに、「いや、そのすべてのリトライが必要だと思います」と言うグループを調査しました。「じゃあ、数字を見せてください。データを見せてください」と言いました。データを調べた結果、2回目のリトライが役立つのは1世紀に1回程度だと結論付けました。その時点で、彼らは5回から1回に減らすことに同意しました。

Thumbnail 1720

リトライする場合は、そのホストからのほとんどすべての呼び出し元でその事実を共有し、ゴシップしてください。誰かが「指数関数的バックオフをしています。100ミリ秒、200ミリ秒、400ミリ秒、800ミリ秒です」と言ったら、それは指数関数的バックオフではありません。その用語の誤用です。それは役に立ちません。そう指摘してください。もし「信じられない」と言われたら、「Jim Roskindのトークの後半を見てください」と言ってください。個々のリクエストに対するリトライだけでなく、全体的なリトライ予算の成長を抑制する必要があります。

Thumbnail 1770

もう一つの本当にクールなことは、超クールになりたいなら、オーバーロード時にもっと効率的になろうとすることです。システムは自然に負荷がかかると効率が落ちる傾向があり、これが最悪の場合、死のスパイラルにつながる可能性があります。これは好ましくありません。システムがダウンするのが好きな人はいますか?良いですね。誰も手を挙げませんでした。ただ皆さんが起きているか確認するためです。システムが稼働し続けるのが好きな人は?あ、全員寝ているわけではないですね。良かった。最適なパターンは、システムがより効率的になることです。ここに引用があります。「今日やらなくてもいいことは明日に延ばしなさい。なぜなら明日になったらそれをやる必要がないかもしれないから」これはプログラマーの格言であるべきです。私の母が教えてくれたこととは違いますが。何か「明日に延ばすな」というようなことでしたが。これがプログラマーの格言です。

Thumbnail 1800

これはどのように機能するのでしょうか?適応的なバッチ処理を考える必要があります。基本的に、リクエストにはいくつかのセットアップコストがあります。物事をまとめてバッチ処理し、セットアップコストを再利用できますか?

Thumbnail 1820

呼び出しの総コストを削減するために?ただし、部分的な成功をサポートする必要があります。バッチ内の単一のリクエストが全体の結果を台無しにするのは望ましくありません。そうでないと、実際に障害が増幅されてしまいます。それは良くないでしょう。

適応的バッチ処理による効率化の実例

例を挙げてみましょう。まず、ワードプロセッサーで見たことがあるような簡単な例から始めます。ここに、ワードプロセッサーを作ったばかりの大学生がいます。彼の基本的なループは次のとおりです:キーボードバッファーから1文字読み取り、その1文字で文書全体を更新し、それが正しく表示されていることを確認するために画面全体を更新します。これを繰り返します。何が問題になるでしょうか?

年配の方なら、多くの古いエディターでこれを見たことがあるでしょう。「ここから約8ページ下に行きたい」と思い、Page Downキーを8回押します。そして画面がゆっくりと更新されるのを見ます。残念ながら、8回押してしまったので、今や大変なことになっています。タイプするスピードを落とさなければならないことに気づき始めます。実際には必要なかったのに、ページ全体をレイアウトしてしまいました。今日やらなくてもよかったことを明日に延ばさなかったのです。

Thumbnail 1890

ページダウンに対する正しくてクールな対応は、キーボードからキーストロークのバッチを読み取り、ドキュメントの最初に変更された行のフォーマットを更新することです。次の行に続くフローについては気にせず、ディスプレイバッファに移動して、更新が必要な画面上の最初の行を更新します。他の行については心配しません。どうせすぐに変更されるでしょうから。そして、これを繰り返します。

私は後にFrameMakerを設立した人物と一緒にこれを実装しました。これにより、8088プロセッサでタイピストがどんなに速くタイプしても追いつくことができました。クールなのは、大量の文字が画面を飛び回るのを目で追うことさえできないことです。タイピングを止めると、ページの残りの部分が表示されますが、それは見ている部分ではありません。これが高速化の一例です。

Thumbnail 1940

では、アプリケーションの世界での例を見てみましょう。価格更新の重複排除を考えてみましょう。単純な実装は次のようになります:製品の価格変更を読み取り、データベースを更新し、別の製品の価格変更を読み取り、データベースを更新する。これは良さそうに聞こえます。しかし、データベースの更新が十分に速くできないために遅れ始めると、キューが増大し始めます。

Thumbnail 1970

では、どうすればより効率的になるでしょうか?答えは、バッファリングされている多数の価格変更を読み取り、それらを製品ごとにソートし、重複を削除することです。まだ処理していない間に誰かが複数回価格を上げた場合、重複を削除します。そうすることで、実際にデータベースへの呼び出しが減ります。システムは進むにつれてより効率的になっていきます。

クラッシュテストの重要性と実施方法

Thumbnail 2000

最後に、これは重要なので持ち帰って必ずシステムをテストしてください。最大負荷を超えてクラッシュテストを行うことです。予想される負荷でのテストだけでは不十分です。状態の崩壊を探ることができません。スケールアップしたと思ったレベルを超えて、失敗するまでテストする必要があります。無制限の遅延に注意してください。それはキューの兆候です。迅速に失敗することは良いことです。大きな遅延を伴ってゆっくりと失敗することは、これらのシステムでは悪いことです。

Thumbnail 2030

問題のあるリトライストームに注意しましょう。面白いことに、これらのリトライストームが集中すると、本来はボトルネックではなかったシステムに過負荷がかかり、そのシステムが他のシステムにレイテンシーの遅延を引き起こし始めます。そうして障害が広がり、多くの場合、崩壊がどこから始まったのかさえ分からなくなります。データ構造全体やフリート全体に広がっていくので、これらの問題のあるリトライストームに注意を払う必要があります。

Thumbnail 2060

そして最後に、過負荷の後、テストコールのレートを通常のレートに戻し、レイテンシーがどれくらい早く回復するかを確認します。1分未満なら良好です。1分以上かかる場合は、見つけなければならない厄介なキューがあることを意味します。そして、Prime Dayに顧客が発見する前に、今日のテストでそれを見つけたいものです。

Thumbnail 2080

これで講演の後半に入ります。そうですね、それを読んでいただけますか。ところで、私はJimです。ありがとうございます。

AWSを使用した輻輳崩壊の検出と監視

皆さん、私たちの周りで起こる輻輳崩壊と、それが実世界のアプリケーションにどのような影響を与えるかについて理解したところで、AWSを使ってこの現象にどのように取り組めるかを探っていきましょう。

Thumbnail 2120

Thumbnail 2130

この話を3つの部分に分けて進めていきます。まず、輻輳崩壊の症状の検出、つまりモニタリングについて話します。次に、そもそもシステムに過負荷をかけないようにする方法について議論します。最後に、輻輳崩壊に関してAWSで採用すべき具体的なテスト方法について説明します。

Thumbnail 2140

検知に関しては、Amazon CloudWatch が CPUUtilization、DiskReadOps、 DiskWriteOps などのメトリクスを標準で提供しています。これらのメトリクスを監視することが重要です。なぜなら、高い CPU 使用率と高いディスク使用率は、輻輳崩壊の典型的な症状だからです。さらに、ユーザー定義のしきい値を設定すべきです。メトリクスがそのしきい値を超えるたびに、アラーム状態となり、インフラ管理者に通知が行きます。例えば、Amazon.com の E コマース部門では、これらのメトリクスを1分ごとに監視し、3回連続(つまり3分間)アラーム状態が続くとインフラチームに通知を送ります。具体的な時間設定は、各企業のビジネスプロセスによって異なるでしょう。

Thumbnail 2190

Thumbnail 2200

Thumbnail 2210

ネットワーキングに関しては、Amazon CloudWatch は NetworkIn や NetworkOut といった集計メトリクスも提供しています。これらは EC2 インスタンスの入出力の総帯域幅を表します。さらに、NetworkPacketsIn と NetworkPacketsOut も監視できます。これらはインスタンスの入出力パケットの総数を示します。これらのメトリクスを監視する際は、通常の日にどの程度の帯域幅とパケット数が見られるかのベースラインを定義し、それに基づいて NetworkIn と NetworkOut が特定の値を超えた場合にアラームを発するしきい値を設定するとよいでしょう。

Thumbnail 2250

これらの集計メトリクスに加えて、環境内でネットワークのスループットに関連して、パケットのキューイングやドロップが発生しているかどうかを理解することが重要です。このために、Amazon CloudWatch の高解像度メトリクスを使用できます。これらの高解像度メトリクスを使用するには、まず Elastic Network Adapter (ENA) をインストールする必要があります。ENA は Amazon Linux 2 や Amazon Linux 2023 など、多くの一般的な AMI にはプリインストールされています。選択した AMI にプリインストールされていない場合でも、後からパッケージとしてインストールすることができます。

Thumbnail 2280

ENA をインストールすると、「1秒あたりのパケット許容量超過」などのメトリクスにアクセスできるようになります。このメトリクスは、EC2 インスタンスが既に1秒あたりの制限に達しているために、パケットのキューイングやドロップが発生しているかどうかを示します。これらのメトリクスを監視し、それに基づいてアラームを設定することで、デプロイメント内でネットワーク輻輳が発生しているかどうかを判断できます。

Thumbnail 2300

Thumbnail 2320

ここで、ロードバランサーに焦点を当ててみましょう。この図は、4つのバックエンドターゲットに負荷を分散している Application Load Balancer を示しています。輻輳崩壊の一般的な症状の1つは、ウェブサーバーからの HTTP 500 エラーメッセージの増加です。昨日から、Application Load Balancer (ALB) は新機能の Automatic Target Weights をサポートするようになりました。これを使用すると、ALB はバックエンドターゲットが HTTP 500 エラーメッセージを増加して送信しているかどうかを追跡できます。そのようなバックエンドインスタンスを検出すると、ALB はそれらを異常としてマークします。

Thumbnail 2360

これらのメトリクスは CloudWatch でも監視できます。メトリクスを追跡すれば、それに応じたアクションを取ることができます。例えば、4つのインスタンスで HTTP 500 エラーの数が増加し、異常と判断された場合、Auto Scaling グループのポリシーを更新して4つのインスタンスを追加することができます。これにより、チームが元の4つのインスタンスで何が起きたのかをデバッグし、原因を突き止める間、短期的に負荷を処理することができます。

Thumbnail 2380

このセクションでは、congestion collapse の兆候を監視するために様々な CloudWatch メトリクスを使用する方法について説明しました。また、CloudWatch でダッシュボードを作成することもお勧めします。ダッシュボードはメトリクスの集合体で、デプロイメントの現状を簡単に可視化し、何らかのアクションが必要かどうかを判断するのに役立ちます。

AWSを活用したWebアプリケーションの過負荷回避策

Thumbnail 2400

では次に、そもそもアプリケーション内でオーバーロードを回避する方法について話しましょう。

Thumbnail 2410

Thumbnail 2420

例として、リージョン内の VPC(Virtual Private Cloud)にデプロイする可能性のある Web アプリを取り上げましょう。VPC は複数のアベイラビリティーゾーンにまたがっている可能性があります。下部に EC2 インスタンスのフリートを示していますが、これらの EC2 インスタンス上でアプリケーションコードを実行している可能性があります。そして、おなじみの ALB(Application Load Balancer)が EC2 インスタンスやバックエンドインスタンスに負荷を分散しています。最後に、ユーザーは ALB にアクセスしてアプリケーションを利用します。

Thumbnail 2440

Thumbnail 2460

Web アプリのオーバーロードを回避する際には、3つの具体的なベストプラクティスがあります。まず、悪意のあるトラフィックを排除すること。次に、ユーザーに早めに引き下がってもらうこと。これは Mother's Day 問題の回避によく似ています。そして3つ目は、アプリケーション内でアップストリームをスロットリングすることです。これは高速道路の流入制御灯の使用によく似ています。

Thumbnail 2470

悪意のあるトラフィックを排除する方法について説明しましょう。まず、静的コンテンツと動的コンテンツのすべてを配信するために Amazon CloudFront を使用すべきです。Amazon CloudFront は世界中に500以上のポイントオブプレゼンスを持つ広範なネットワークを有しており、ユーザーに低レイテンシーを提供します。さらに、この広大なフットプリントにより、DDoS攻撃をEdgeレイヤーで吸収できるため、システムへの負荷を軽減できます。CloudFrontを使用すると、ユーザーリクエストはまずEdgeロケーションのCloudFrontに到達し、必要に応じてリクエストやトラフィックがバックエンドターゲットに戻ります。

Thumbnail 2500

Thumbnail 2510

Thumbnail 2530

次に、AWS Shield Advancedを使用して、DDoS攻撃をEdgeで検出してブロックすべきです。そして最後に、Webアプリケーション用のルールを作成できるAWS Web Application Firewall(WAF)を使用すべきです。これらのルールを使用することで、悪意のあるトラフィックをEdgeで検出し、拒否することができます。悪意のあるトラフィックを排除するために、Amazon CloudFront、AWS WAF、AWS Shield Advancedのこれら3つのサービスを組み合わせて使用すると、悪意のあるトラフィックはEdgeロケーションで検出され、拒否されます。そのため、そのトラフィックがアプリケーションの下流に到達することはなく、システムへの負荷を軽減できます。

Thumbnail 2550

次に、ユーザーに早めに控えめにするよう求める方法について説明しましょう。前のセクションで、Jimは母の日の問題と、電話会社がその問題をどのように解決したかについて話しました。電話会社は、ユーザーに事前録音されたメッセージを流すことで対応しました。そのメッセージは、問題が電話会社側にあることをユーザーに明確に伝え、いわゆる更新ボタンを5回連続で押さないようにしました。では、AWSで偶発的な過負荷を回避する方法を見てみましょう。

Thumbnail 2580

Thumbnail 2600

AWS WAF(Web Application Firewall)を使用すると、ユーザーにカスタムレスポンスコードを送信できます。具体的な設定例として、WAFにレート制限ルールを作成することができます。レート制限ルールは、Webアプリケーションに対して入ってくるリクエストの総数を監視します。このレート制限ルールを超えた場合、HTTP 429コードやカスタムWebページをユーザーに返すことができます。

Thumbnail 2620

amazon.comの話をしているので、Amazonは実際にカスタムエラーページを表示する素晴らしい仕事をしています。これは、amazon.com側に問題がある場合に表示される「Dogs of Amazon」ページです。このページは、問題が遠隔地にあることをユーザーに知らせます。さらに重要なのは、問題がユーザーのブラウザやインターネット接続にないことを伝えている点です。これにより、ユーザーはアプリケーションにアクセスするために1秒間に3回も更新ボタンを押す必要がないことを理解します。これが、人間の行動に影響を与え、正当なユーザーが偶発的に過負荷を引き起こす状況を回避するためのメカニズム、つまりAWSのメカニズムなのです。

Thumbnail 2660

では、アプリケーション内でどのようにアップストリームをスロットリングできるかについて話しましょう。アプリケーション内での話なので、リクエストはすでにアプリケーションレベルにあると仮定します。これは全て正当なトラフィックです。Jimはサービス指向アーキテクチャについて話しました。このようなアーキテクチャでは、複数の異なるコンポーネントが集まってアプリケーションを構築します。そのようなアプリケーションでは、コンポーネント間の相互作用を理解することが非常に重要になります。

サービス指向アーキテクチャにおけるアップストリームスロットリング

Thumbnail 2700

例を見てみましょう。ここでは、アプリケーションの2つのコンポーネント、Service-1とService-2を示しています。次の数枚のスライドでは、サービスとアプリケーションコンポーネントという用語は互換的に使用されます。この例では、上部のService-1が下部のService-2と直接通信しています。

この直接的な通信は、密結合アーキテクチャの例です。サービス指向アーキテクチャでは、異なるソフトウェアエンジニアリングチームがアプリケーションの異なるコンポーネントを所有し、それぞれのコンポーネントに対して異なる自動スケーリングポリシーを持つ場合があります。

Thumbnail 2740

Service-1がService-2よりも速くスケールアウトするシナリオを考えてみましょう。Service-1は引き続きメッセージやリクエストをService-2に送り続けますが、Service-2はService-1ほど堅牢ではありません。その結果、キューが蓄積し始めます。最終的には、Service-2内のすべてのインスタンスのCPU使用率が100%に達し、キューサイズは増大し続け、生産的な作業が行われなくなる可能性があります。

Thumbnail 2770

Thumbnail 2790

この問題を避けるために、疎結合システムを使用すべきです。この場合、上部のコンポーネントはメッセージのプロデューサーとなり、Amazon Simple Queue Service(Amazon SQS)のようなブローカーシステムにメッセージを配置します。そして、コンシューマーがキューからそれらのメッセージを取得します。コンシューマーがメッセージをプルしているため、アプリケーションはプルベースモデルで動作し始めます。コンポーネントが互いに直接通信していないため、これはアプリケーションの一つのコンポーネントが他のコンポーネントを圧倒したり、過負荷にしたりしないようにするAWSのメカニズムとして機能します。

実世界のユースケースを考えてみましょう。タクシー配車サービスやeコマースプラットフォームのようなビジネスでは、価格がいつでも変更される可能性があります。このようなシナリオでは、アプリケーションが貴重な処理リソースを、最新の価格情報などの最新のメッセージの処理にのみ投資していることを確認したいと思います。

Thumbnail 2870

ここで、コンシューマーがすでに過負荷状態にあり、おそらく前のメッセージの処理に長時間かかっている状況を考えてみましょう。プロデューサーはこれを知らずに、SQSキューにさらにメッセージを送り続けます。 キューが増加している間、SQSはフルマネージドサービスとして、水平スケーリングによってこの負荷を処理できます。しかし、コンシューマーの観点からすると、リソースが最終的に解放されたときに古いメッセージを処理してしまう可能性があり、これは無駄な支出になる可能性があります。

Thumbnail 2930

Thumbnail 2950

この問題に対処するために、高速道路の信号機のような上流でのスロットリングメカニズムを実装できます。まず、システムが混雑しているかどうかを判断する必要があります。 キューの深さの増加は、これの良い指標となります。SQSのApproximateAgeOfOldestMetricメトリクスを使用できます。これはキューの深さを示します。このメトリクスはAmazon CloudWatchで追跡でき、そこでしきい値を定義できます。 キューサイズがこのしきい値を超えた場合、そのメトリクスにアラームを設定し、対応するアクションを取ることができます。

Thumbnail 2970

Thumbnail 3000

この場合、対応するアクションは、コンシューマーが混雑しているときにプロデューサーに減速を知らせるAWS Lambda関数を持つことです。 このメカニズムにより、特に高トラフィック期間中にアプリケーションの負荷を上流でスロットリングしてメーター制御することができます。プロデューサーがスロットリングされている間、コンシューマーは最終的にSQSキューからメッセージを取得し始めます。 時間とともに、キューサイズは再び健全になります。

Thumbnail 3050

そして、このメトリクスが健全になったら、Lambda関数はプロデューサーのスロットリングを停止できます。この時点で、プロデューサーはSQSキューへのメッセージの送信を再開できます。ここで自然な疑問は、スライドには2つのコンポーネントしかありませんが、3層のWebアプリや4層のWebアプリの場合はどうでしょうか?複数のコンポーネントがある場合はどうでしょうか?そのような状況では、同じメカニズムをカスケード方式で使用し、アプリケーションの最上位コンポーネントに到達するまで各レベルで上流をスロットリングできます。そして、アプリケーションの最上位コンポーネントの上には何がありますか?ユーザーです。そして、ユーザーに早めに引き下がってもらうにはどうすればよいでしょうか?これは前のセクションで議論した、カスタムエラーページを表示することで実現できます。

AWSを用いたアプリケーションのクラッシュテストとカオスエンジニアリング

Thumbnail 3100

このセクションでは、システムの過負荷を回避するためのさまざまなテクニックについて説明しました。次はテストについて話しましょう。前のセクションで聞いたように、Amazon.comはクラッシュテストの手法を採用しています。これは、アプリケーションを故障点まで、そしてそれ以上にテストする方法です。ただし、Amazon.comに焦点を当てると、Amazon.comと同じ規模のテストベッドやテスト環境を作成し、ストレステストやクラッシュテストを行うのは非常に難しいでしょう。そのため、アプリケーションのシミュレーションや小規模モデルを作成する必要があります。

Thumbnail 3120

Thumbnail 3140

ここで、約束した猫の写真が登場します。あなたの全体的なデプロイメントがこの大きな灰色の猫で表されているとすれば、アプリケーションの子猫バージョンを作成し、それをしっかりと動作させる必要があります。ここで、もう一度サービス指向アーキテクチャの話に戻りましょう。あなたのアプリケーションが10の異なるコンポーネントで構成されているとします。この小規模アプリを作成する際、すべての依存関係をテストする必要があります。なぜなら、このテスト方法によって、特定のコンポーネントをクラッシュテストした際に、他のコンポーネントに悪影響があるかどうかを知ることができるからです。そして最後に、アプリケーションの各層や各コンポーネントを個別に、または独立してクラッシュテストする必要があります。これにより、アプリを構成する様々なコンポーネントに弱点があるかどうかを知ることができます。

Thumbnail 3160

Thumbnail 3200

次はトラフィックについて話しましょう。テストサイクルで使用すべきトラフィックには2種類あります。まず、Amazon VPC traffic mirroringのようなテクニックを使用して、正当なユーザーから得られる実際のトラフィックをキャプチャする必要があります。VPC traffic mirroringを使用すると、Elastic Network Interfaceのトラフィックをキャプチャして目的地に送信できます。トラフィックが目的地に到着したら、PCAPファイルに保存し、テストサイクル中に再生することができます。ただし、同じトラフィックを何度も再生していると、システムが情報をキャッシュし始める可能性があります。システムがフロー情報をキャッシュしてしまうと、アプリケーションを本当の意味でストレステストやクラッシュテストすることができなくなります。これを軽減するために、iPerfのようなオープンソースツールを使用して、新しいトラフィックやシミュレートされたトラフィックを追加することもお勧めします。

Thumbnail 3210

Thumbnail 3240

Thumbnail 3250

Thumbnail 3260

これで、考慮すべき2つ目のテスト方法であるカオスエンジニアリングの原則に話が移ります。これは、環境に人為的な障害を挿入し、それらの障害が導入されている間にアプリケーションがどのように動作するか、そしてそれらの障害を導入したときのユーザー体験がどうだったかを観察することを意味します。ただし、これらの障害は必ずメンテナンス時間帯にのみ挿入してください。これらの障害を挿入するには、AWS Fault Injection Simulator(FIS)と呼ばれるAWSサービスを使用できます。FISを使用すると、実験テンプレートを作成し、それらの実験を実行することができます。これらの実験には、インスタンスの障害をシミュレートする(インスタンスがダウンして再起動した場合どうなるか)、ネットワークの障害をシミュレートするなどがあります。後者の例としては、2つのアベイラビリティーゾーン間の通信を妨げる可能性のある不適切なネットワークアクセスコントロールリストエントリがあります。

Thumbnail 3270

Thumbnail 3280

Thumbnail 3290

高CPU使用率が輻輳崩壊の典型的な症状であることについて話していましたが、FISを使用して、インスタンスの高CPU使用率もシミュレートできます。こちらは実行中のFIS実験のスナップショットです。このFIS実験は、EC2インスタンスで高CPU使用率を引き起こします。この実験が実行されている間、対応するCloudWatchメトリクスはCPU使用率が急上昇したことを示しています。このように、メンテナンス時間帯にデプロイメントにこのような障害を挿入することで、2つの利点が得られます。まず、障害時のアプリケーションの動作と、その間のユーザー体験を理解することができます。

Thumbnail 3330

次に、これはあなたの運用手順書が事業をサポートする方法で設定されているかどうかを知る手がかりにもなります。例えば、このテストが実行されている間、5分間インスタンスのCPU使用率が99%になりましたが、それに対してアラームが発生しましたか?適切なインフラ管理者に通知されましたか、それとも通知されませんでしたか?

Thumbnail 3340

Thumbnail 3350

さて、これまで議論したことをまとめましょう。まず、環境内の輻輳崩壊の兆候を監視するために使用できる具体的なAmazon CloudWatchメトリクスについて説明しました。次に、輻輳崩壊がいかに状態依存的な現象であるかを説明し、そのため可能な限り回避することが最善であると述べました。そのために、3つの具体的なベストプラクティスについて説明しました。

1つ目は、悪意のあるトラフィックを排除することです。Amazon CloudFront、AWS WAF、AWS Shield Advancedなどの AWS Edge Servicesを組み合わせて使用する方法について説明しました。2つ目は、AWS WAFのレート制限ルールとカスタムレスポンスコードを使用して、早い段階でユーザーに控えめにアクセスするよう要求し、いわゆる「母の日問題」を解決する方法について説明しました。そして3つ目は、Amazon SQSとAWS Lambda関数を使用してアップストリームを抑制し、アプリケーションのハイウェイの渋滞を防ぐ方法について説明しました。

Thumbnail 3390

最後に、テストに関しては、2つの具体的な推奨事項があります。まず、カオスエンジニアリングの原則を採用することです。これは、環境に人為的な障害を挿入し、アプリケーションを故障点まで、そしてそれ以上にテストすることを意味します。これはクラッシュテストの原則としても知られています。

Thumbnail 3440

さて皆さん、このセッションが役立ったことを願っています。JimとI(私)は、皆さんの時間を割いていただいたことに感謝します。モバイルアプリでセッションのアンケートにご記入ください。これらのセッションが有用であるかどうか、そして同様のセッションを今後も開催すべきかどうかを判断する材料となります。


※ こちらの記事は Amazon Bedrock を様々なタスクで利用することで全て自動で作成しています。
※ どこかの機会で記事作成の試行錯誤についても記事化する予定ですが、直近技術的な部分でご興味がある場合はTwitterの方にDMください。

Discussion