AWSを利用するときにありがちな7つの考慮漏れ
AWSを使ってて色々引っかかるパターンを見たわけなので、考慮が漏れるようなケースをまとめておく。
アプリケーションを実装するときの考慮点が多め。
記事中の「APIコール」はAWS CLIやSDKを通じて、AWS側の処理を呼び出す箇所を指すものとしている。
- 1. APIコールが失敗するケースを考慮しない
- 2. スロットリングを考慮しない
- 3. 特定インスタンスタイプのみでEC2起動やスケールアウトが無限にできる前提にする
- 4. 分散データ系サービスの結果整合性を考慮しない
- 5. APIコールが成功した後、後続処理も100%成功すると考える
- 6. APIコールでエラーが発生した場合、期待した処理も必ず行われていないと考える
- 7. AWS CLIやSDKがAPIコールを2重実行する可能性を考慮しない
- まとめ
1. APIコールが失敗するケースを考慮しない
各種APIコールがほぼ100%成功する前提で実装してしまうケース。
99.9…%程度は成功するようにできているが、何度も処理される箇所で使ってると大抵どこかでエラー発生に出くわす。
API利用をする場合、常にエラーハンドリングを考慮して実装し、テストするクセをつけておきたい。
2. スロットリングを考慮しない
AWSのAPIコールは単純に発行回数が多すぎるだけでスロットリングエラーとなるものがある。
通常、上限がある場合はAWS側で明示しているのでまずは把握することが大事。
大量にAPIコールを行う場合、スロットリングが発生しない程度に負荷分散するようにするか、発生してもリトライできる仕組みを整えるあたりが妥当。
3. 特定インスタンスタイプのみでEC2起動やスケールアウトが無限にできる前提にする
スケールアップの限界は最大のインスタンスタイプを見ればすぐわかるが、数を増やすことにも限界があることは考慮が漏れがち。用意している仮想サーバの数も有限である。
例えば特定のタイプが世の中で大量に起動されていて余りが無ければ、新規に起動することができないといったことが発生する。
起動できないケースがクリティカルな場合は、リザーブドインスタンスで事前購入して確保しておくか、起動しない場合に別タイプで代替することを考慮する。
※ EC2のみではなく、他サービスでも同様のことは発生はする認識
4. 分散データ系サービスの結果整合性を考慮しない
DynamoDBやS3など、分散データを持つサービス利用時に影響する。
例えばデータやファイルをA→Bに更新し、直後に取得すると古いAが取得される可能性もあるというケース。結果整合性の性質上、何秒以内なら発生するといった閾値があるわけでもない。
これは考慮が漏れた場合、発生率が低くて単純にテストしてもすり抜けるし、問題が発覚した時の再現-改修検証も面倒なことになる。
ドキュメントからのサービス仕様把握、コストが許すならサポート契約+問い合わせ、実機検証などで考慮が漏れていないかは事前に確認する。
なお、DynamoDBは設定で強整合性での取得もサポートされており、S3ならPUT時に返却されるETagを取得APIに付与すれば想定するファイルのみが取得対象となるように制限はできる。
5. APIコールが成功した後、後続処理も100%成功すると考える
例えばEC2起動を指示して成功が返却されたとしても「起動処理の受付」に成功したに過ぎない。
EC2が起動するまでのプロセス中に問題が発生し、pending状態のままでrunningに遷移しないといったことは発生する。
ステータスのポーリングを繰り返すか、CloudWatch Eventsと連携してEC2インスタンスの状態を記録し、一定時間runningにならなければアラート・強制停止などのハンドリングを組み込む。
6. APIコールでエラーが発生した場合、期待した処理も必ず行われていないと考える
逆もあるんかいとなってしまうが、仕組み上はあり得る話でタイムアウトでエラーとなったケースでたまに見ることがある。
APIコール
→AWS側が長時間で処理成功
→クライアントがタイムアウトエラー
ということが発生する。
「エラーとなったのに処理が成功してる」となっても慌てず、「エラー内容がタイムアウトならばこういうこともある」と判断できると障害切り分けなどが少し捗る。
7. AWS CLIやSDKがAPIコールを2重実行する可能性を考慮しない
タイムアウトしたけど成功してしまうケースとリトライの合わせ技で発生。特別なリトライ設定をするわけでもなく、SDKが実装しているリトライ機構を使うだけで発生する。
APIコール
→AWS側が長時間で処理成功
→クライアントがタイムアウトエラー
→エラーリトライでAPIコール
というルートで勝手に2重処理が実行されてしまう。
具体例では、キー重複を許さないDynamoのデータPUTで、自分が登録したものに対してリトライして勝手に重複エラーを起こすといったことも発生する。
まずは処理の冪等性を担保し、それができない場所では2重処理されてもそれを検知して問題ないようにハンドリングする対処を入れておきたい。