「502 Bad Gateway」「504 Gateway Timeout」の解決事例について
皆様こんにちは。tamです。
「502 Bad Gateway」
「504 Gateway Timeout」
いきなりですが、自社のサイトを閲覧しようとした際に上記のようなメッセージが表示されたことはありませんか?
「昨日まで問題なく閲覧できたのに今日いきなり見えなくなった!」
「急にページが表示できたり、また表示できなくなったり、どうなっているんだ!?」
上記のような無機質な英文エラーメッセージしか表示されず、何が起こっているのかわからない状態です。
ただし、このままでは販売機会を逃したり、サイトおよび会社のイメージダウンに繋がってしまうため、一刻も早く解決する必要があります。
ところが困ったことに「502 Bad Gateway」「504 Gateway Timeout」が起こる原因は1つではないのです。
今回は実際に上記エラーを解決した対応のうち、少し特殊な例ついてお話したいと思います。
環境について
AWSで以下のような構成です。
- EC2(Apache+PHP)が1台
- RDS(MariaDB)が1台
症状(障害内容)について
- お昼頃からページが表示できたりできなかったりするが、夕方の日もある。
- 同じページでも人によっては正しく表示できる場合もある。
- サイト公開から今まで同様の症状が発生したことはない。
- 障害が起こり始める前にサーバーの設定変更や、プログラムの書き換えは行っていない。
- 直近で大がかりなプロモーションは行っておらずアクセス数が数倍になったりはしていない。
よくある「何もしていないのにおかしくなった!」ってパターンですね。
何もしていないのにどうして障害が起こるようになってしまったのでしょう…?
原因はいったい…!?
結論から言ってしまうと原因はRDSにありました!
RDSの汎用SSDボリューム(gp2)はストレージサイズに応じてIOPSが変動します。
IOPSとは「Input Output Per Second」の略で1秒あたりのディスクに対する読み込み/書き込み能力を表します。
具体的な数値としては1GiBあたり3 IOPSが割り当てられます。
つまりストレージサイズが100GiBの場合だと300 IOPSになるというわけです。
この値を「ベースラインパフォーマンス」と呼びます。
普段のI/O需要が「ベースラインパフォーマンス」の範囲内の場合、全く問題になりません。
突然の悲劇!!
ところが、この値を上回った時!悲劇が始まるのです!!!
最初は540万(I/O)のクレジット(貯金)があり、毎秒ベースラインパフォーマンス分(300 I/O)ずつ増えていきます。
よってI/O需要が300 IOPSに収まっている間はクレジットが減ることはありません。
では仮に1,000 IOPSの需要があった場合はどうでしょう?
毎秒700(I/O)不足することになるので以下の計算になります。
5,400,000 ÷ 700(I/O) = 7,714(秒)
つまりたった2時間ほどで貯金を食いつぶしてしまうのです。
クレジットが枯渇してしまうと1,000 IOPSの需要があっても300 IOPSの性能しか発揮されません。
詳細な内容はコチラをご確認ください。
公開したサイトのアクセスが少ない間は問題にならずとも少しずつアクセスが増え、ある日から300 IOPSを超えます。
日中はクレジットを消費しつつも明け方などアクセスの少ない時間は逆にクレジットが蓄積されており動作上は問題ありません。
そうやって目に見えぬ導火線の炎は少しずつ近づいてきて、ある日突然!爆発するのです!
日中700(I/O)の消費が2時間続いた段階でクレジットが枯渇
↓
1,000 IOPSの需要に対して300 IOPSの性能しか発揮されない
↓
RDSで処理がどんどんと溜まり続ける
EC2のバックエンドとして動作しているRDSがこのような状態になってしまうと、サイトとして正常に動作しなくなってしまいます。
困ったことにすべてのPVに対してエラーになるわけではなく…
- 一部は正常に動作
- 一部は遅れて動作
- 一部は接続エラー
日、時間、人によって動いたり動かなかったりと原因の特定が非常に難しい障害となってしまいます。
これを解決するためには「ベースラインパフォーマンス」を引き上げる必要があります。
解決法 その1
それはストレージサイズを増やすことです。
ストレージサイズを100GiBから300GiBに変更するとベースラインパフォーマンスも3倍となり900 IOPSになります。
1,000 IOPSの需要があったとしても900 IOPSあれば…
5,400,000 ÷ 100(I/O) = 54,000(秒)
おおよそ15時間もの間、需要を満たすことができます。
残りの9時間でまた貯金できれば障害は起こりません。
ただし、ストレージはコストが発生しますので必要以上に大きいサイズを用意すると無駄になります。
解決法 その2
それはgp2からgp3 ストレージボリュームに変更することです。
RDSでもgp3が利用できるようになりました。
MariaDBの場合、gp3では400GiBまでは3,000 IOPSが確保されているので1,000 IOPSの需要があっても余裕で対応できます。
そして400GiB以上ではなんと!
12,000 IOPSに引きあげられます。
大切なことなのでもう一度…
12,000 IOPSに引きあげられます。
EBSのgp3では400GiB以上であっても3,000 IOPSのままなのでこの追加仕様はすごくうれしいですね。
ただしRDSのDBエンジンによって少し仕様が異なります。
Oracleの場合だと200GiB以上で12,000 IOPSになり、SQL Serverの場合は残念ながら3,000 IOPSのままです。
詳しくはコチラ(英文)をご参照ください。
最後に
いずれの解決方法を採用する場合であっても、無駄なコストを発生させないため最適な選択をする必要があります。
そのためにも普段から監視を続けることが重要です。
また、監視を行うことによって障害を発生させず未然に防ぐことができる場合もあります。
どのような項目をどのような方法で監視すればいいのかなど、詳しく知りたい方は一度お気軽にご相談ください。