このすみ技術ろぐ

とあるWebエンジニアが、技術や趣味について書くブログです。

Laravelのキューワーカー(queue:work)はソースコード反映に再起動が必要だった件

とあるプロジェクトに開発支援で参加しているのですが、最近トラブルが発生していました。 原因は不明なのですが、Laravelのキューワーカー経由で実行されるJobが、異常終了してしまう問題です。

なぜかlaravel.logにも怪しいエラーメッセージが残っておらず、途方に暮れていました。 トラブルは長続きして数日間悩まされたのですが、無事に解決できたので、原因と対処法を共有します。

Laravelのキューワーカー(queue:work)は常に動いている

まず原因ですが、 php artisan queue:work ~ で実行されているキューワーカーが、1年以上動きっぱなしであることが原因でした。 つまるところ、キューワーカーは1年以上前のソースコードの状態で動き続けていたのです。

キューワーカーを再起動したら直った

紆余曲折ありましたが、結果的にはキューワーカーを再起動したら、トラブルは改善しました。 根本原因は、最新のシステム(主にデータベース)状態と、1年以上前のソースコードで動き続けていたキューワーカーとの不整合 によるものです。

改善案

キューワーカーが古いソースコードで動き続けてしまう問題を回避する案としては、2つほど思い浮かびました。

1. デプロイ時にキューワーカーを再起動する

1つ目の選択肢は、ソースコードのリリース時にキューワーカーを再起動するというものです。 方法としてはシンプルですが、リリース時に毎回となると手間も大きいので、デプロイを自動化しているかどうかが鍵となります。

キューワーカは長時間起動プロセスであるため、リスタートしない限りコードの変更を反映しません。
ですから、キューワーカを使用しているアプリケーションをデプロイする一番シンプルな方法は、デプロイ処理の間、ワーカをリスタートすることです。 queue:restartコマンドを実行することで、全ワーカを穏やかに再起動できます。 参考: https://qiita.com/_hiro_dev/items/eef6778179e692507c84 より

2. キューワーカーを動き続けずに常駐させる仕組みに変更する

2つ目の選択肢は、キューワーカーが動き続けてしまう仕組みを改善するというものです。 --onceオプションや--stop-when-emptyオプションを活用します。

--onceオプションは、ワーカにキュー中のジョブをひとつだけ処理するように指示します。
--stop-when-emptyオプションは、すべてのジョブを処理してから終了するように、ワーカへ指示するために使用します。
参考: https://qiita.com/_hiro_dev/items/eef6778179e692507c84 より

Laravelのキューワーカーが仕事を終えたら毎回終了させることで、常にキューワーカーが起動し続ける運用をやめます。 その代わり、crontabなどで定期的に実行するようしておけば、自動的に新しいソースコードで動いてくれるという算段です。

www.blog.danishi.net

まとめ

Laravelのキューワーカー(queue:work)が常駐で動き続けている事実を、トラブルが発生した後に知ったため、原因究明と改善に時間がかかってしまいました。 システムの理解度が不足していたことを痛感しているのですが、良い勉強にはなりました。

ソースコードが新しくならない問題は、Laravelのキューワーカー以外でも、ブラウザのJSやCSSキャッシュなど身近でもよくハマります。 ある意味で、Webエンジニアあるあるかもしれません。