ShoryukenをアップデートしたらSQSからデータを受信する頻度が変化してしまった件
ストリーミングデータを扱う際や外部システムと連携する際に、メッセージキューイングサービスであるAmazon SQS(以下、SQS)がしばしば用いられます。私自身、普段はRubyでシステムを開発することが多いため、SQSクライアントとして「Shoryuken」というRubyGemを使っています。
今回、数年前に開発したシステムのRubyGemsをアップデートする機会があり、Shoryukenのバージョンを上げたところ、SQSからデータを受信する頻度が低下するという事象が発生しました。
本記事ではその原因や対処法をまとめます。
発生した事象
Shoryukenをアップデートによって、SQSにエンキューされたメッセージがデキューされるまでに40〜80秒程度かかるケースが散見されるようになりました。
アップデート前はほぼ即座にデキューされていました。
発生条件
開発していたシステムでは次のような条件でShoryukenを使用していました。
-
batch: true
を指定している- SQSからメッセージをまとめて受信できるようにするオプションです
- https://github.com/ruby-shoryuken/shoryuken/wiki/Worker-options#batch
- アップデート前はバージョン4を使用しており、アップデートによりバージョン5以降となった
- 具体的には
4.0.3
→6.2.1
のアップデートをしました
- 具体的には
- アップデート前からConfigurationにて
delay
を指定していた- SQS内にメッセージがなかった場合にフェッチを一時停止する秒数を指定するパラメータです
- https://github.com/ruby-shoryuken/shoryuken/wiki/Shoryuken-options#delay
原因
アップデートによってバージョンが上がったことで、これまで機能していなかった delay
オプションが仕様通りに機能するようになり、SQSへのフェッチ周期が下がったためです。
バージョン4以前のShoryukenは batch: true
を指定しているときに delay
の指定が機能しないという問題を抱えていました。
この問題が2019年6月に修正され、バージョン5としてリリースされていたようです。
ちなみに、このシステムでは delay
を 60
と指定していたため、アップデート後は1分間に1回、SQSに問い合わせする挙動となっていました。
本システムではタイムアウト20秒のロングポーリングを行っていたため、問い合わせ開始から20秒が経過した後にメッセージをエンキューされると、そこから最大40秒間はデキューされない挙動となっていました。
対処
フェッチ周期がアップデート前と同じになるよう、 delay
を 0
としました。
※そもそも、アップデート前は 60
が指定されていましたが、これは機能していなかったということになります。
SQSへのフェッチ周期も元通りになっていました。
再発防止
本システムはテストコードが十分に記述されており、自信を持ってアップデートを行っていたという状況だったため、どうすればもっと早くこの問題に気づけたのか、頭を抱えているというのが正直なところです。
一つ言えることとしては、アップデート前後で各種AWSリソースのメトリクスの傾向に変化がないか、目視確認をしておけば早期に問題に気づけたかもしれません。
有効な再発防止は現時点で思いついていないため、良い方法があればこっそり教えていただけると幸いです。
感想
RubyGemsのアップデートは一筋縄ではいかないだろうと、当初から予想はしていたものの、ユニットテストやE2Eテストではなかなか気づきにくい「性能問題の厄介さ」を痛感しました。
問題を未然に防ぐことはできませんでしたが、問題が明らかになってからはメトリクスを確認したり、ShoryukenのIssueを探して関連のある事象をスムーズに特定できたので、その点は良かったと考えています。
この経験を活かし、より安全なRubyGemsのバージョンアップについて、考えていきたいです。
Discussion