ApproximateAgeOfOldestMessage
とは?
SQS には ApproximateAgeOfOldestMessage
というメトリクスがあり,CloudWatch でモニタリングをすることができる.なお,SQS の歴史を考えると比較的最近に追加されたメトリクスで,2016年8月にリリースされている.
ApproximateAgeOfOldestMessage
の意味を公式ドキュメントから引用すると,以下の通りとなる.ようするに,SQS に登録されているメッセージの中で「最も古い」メッセージの「登録されてからの経過時間(秒)」と言えるため,例えば SQS をポーリングするようなアプリケーションが障害で停止しているような場合は ApproximateAgeOfOldestMessage
の値が増えるため,異常を検知することができる.
キューで最も古い削除されていないメッセージのおおよその経過期間。
逆に,夜間帯にポーリングしないという仕様のアプリケーションだった場合は,夜間帯に ApproximateAgeOfOldestMessage
の値が増えて(期待値),翌朝にポーリングをすると ApproximateAgeOfOldestMessage
の値が 0 に戻る(期待値).実際にこのようなアプリケーションを運用していて,以下のようなグラフになっている.
(夜間帯にポーリングを止めている状態)
最近起きた事象
最近,特定のメッセージがアプリケーションでエラーになり,可視性タイムアウト (Visibility Timeout) が終了したら SQS にメッセージが戻されて,リトライを繰り返す状況が起きていた.アプリケーションのバグは想定していたため,このような状況を ApproximateAgeOfOldestMessage
の値で検知するはずだったけど,なぜか ApproximateAgeOfOldestMessage
の値が定期的に下がってしまうという事象が起きた.なお,参考のために SQS の設定を一部抜粋する.
- 可視性タイムアウト : 30分
- DLQ (Dead-Letter Queue) : 設定なし
ApproximateAgeOfOldestMessage
の CloudWatch アラーム : 設定あり
以下のグラフを見るとわかる通り,なぜか「90分間隔(可視性タイムアウトとも関連性がない)」で ApproximateAgeOfOldestMessage
の値が下がってしまっていた.また,アプリケーション側のリトライによってメッセージの受信数も増えていて,SQS に登録されてからの経過時間は ApproximateAgeOfOldestMessage
の値よりもずっと長かったため,ずっと線形に値が増えていくことを想定していた.
もう1度 ApproximateAgeOfOldestMessage
の定義を振り返ると「キューで最も古い削除されていないメッセージのおおよその経過期間」なので,勝手に下がってしまうというのは変だなと感じて,AWS サポートに問い合わせた.
(定期的に ApproximateAgeOfOldestMessage
の値が下がってしまった状態)
ポイズンピルメッセージがあると ApproximateAgeOfOldestMessage
の値が正しくなくなる可能性がある
AWS サポートに問い合わせてわかった結論としては,ポイズンピルメッセージ(アプリケーションでエラーになって SQS に戻ったメッセージのこと)があると ApproximateAgeOfOldestMessage
の値が「正しくなくなる可能性がある」という仕様だった.メトリクスのドキュメントには載っていなかったけど,以下の「全般的な推奨事項」には確かに載っていた.これって結構知られている仕様?
キューにポイズンピルメッセージを含めると、ポイズンピルメッセージの誤った経過期間を指定することで、ApproximateAgeOfOldestMessage CloudWatch メトリクスが正しくなくなる可能性があります。デッドレターキューを設定すると、このメトリクスを使用する場合の誤ったアラームの回避に役立ちます。
ドキュメントを見ると,今回の件は「DLQ を活用して回避する」と載っているけど,例えば DLQ を活用するとしても最大受信数を設定して DLQ に飛ばすため,DLQ を活用したからと言ってポイズンピルメッセージを撲滅できるわけではないと理解している.そういう意味で,今回の件を通して感じたのは ApproximateAgeOfOldestMessage
のモニタリングに頼りすぎるのは危険だと思った.あくまで ApproximateAgeOfOldestMessage
は参考値として考えて,DLQ の ApproximateNumberOfMessagesVisible
などのメトリクスをモニタリングした方が良さそう.
まとめ
- SQS のメトリクス
ApproximateAgeOfOldestMessage
の値は,ポイズンピルメッセージがあると「正しくなくなる」可能性がある- ドキュメントに載っている「正しくなくなる」は,今回の事象では「定期的に値が下がる」だった
- メトリクスのドキュメントにはその仕様が載っていないため注意する
- モニタリングをする場合は
ApproximateAgeOfOldestMessage
の値ではなく,DLQ を用意してApproximateNumberOfMessagesVisible
などを活用する - 今まで知らなかった SQS の仕様を勉強できて良かった👍