Tweet
Logo
    Laravel Worker が ECS の Scale In でエラーを吐かないようにする
    Laravel Worker が ECS の Scale In でエラーを吐かないようにする

    Laravel Worker が ECS の Scale In でエラーを吐かないようにする

    • はじめに
    • Worker 周りの構成
    • Scale In の課題
    • 対策
    • 終わりに
    • 参考資料

    はじめに

    DROBE では外部のサービスを利用したメールの送信など、時間の掛かる処理を行う際に Laravel の Worker を多用しています。

    この記事では、ECS Fargate を Worker として使用した際に安定稼働させるための Tips を共有します。

    Worker 周りの構成

    DROBE では Laravel の Worker が使う Queue driver に AWS の SQS を採用しています。

    Worker は ECS Fargate を利用していて、CloudWatch が SQS の詰まり具合を監視し、詰まり具合に応じて Worker Service を通して Worker コンテナの Scale Out / In を行っています。

    DROBE の Worker 周りの構成
    DROBE の Worker 周りの構成

    この構成にしておく事で、Queue に Job が大量に積まれると自動で Worker が増えて Job の並列数があがり、Job が減ってくると自動で Worker を減らす事が出来ます。

    例えばメール通知を Job でやっている場合に特定の時間にメール送信が集中するといった場合などに有効な構成だと思っています。

    Scale In の課題

    この構成において Scale out に関しては特に問題などなく運用が可能なのですが、 Scale in に関しては気をつけないと Job を処理中の Worker が途中で死んでしまいます。

    何らかの要因で ECS Task に終了の命令が出されると ECS Task は一定時間後に終了します。命令が出されてから終了するまでの時間はデフォルトで 30 秒ですが、ECS の Task 定義の設定によって 120 秒まで伸ばす事が出来ます。

    ここで Laravel の以下のコマンドで起動したプロセスは SIGTERM を受信した後も job を dequeue しようとしてしまいます。

    php artisan queue:work

    つまり、以下の図のように Scale in のタイミングによっては Worker が job を処理している途中でプロセスが終了する事になってしまいます。

    ECS で Laravel Worker を動かしていると Scale in で job が失敗する可能性がある
    ECS で Laravel Worker を動かしていると Scale in で job が失敗する可能性がある

    結果として不定期でこのようなエラーが鳴り響く、という事態となってしまいます。

    sentry に記録されたエラー
    sentry に記録されたエラー

    弊社では Worker で行う内容は基本的に冪等性を担保して作っているので必要があれば再実行すれば良いのですが、精神衛生上とってもよろしくない状況となってしまっていました。

    対策

    この問題に対応するためには、SIGTERM が来たら job を dequeue しないようにしてあげる必要があります。

    この記事を参考に、worker 用の entry point となるスクリプトを準備しました。

    #!/bin/bash
    
    exit_trap(){
      echo "received SIGTERM, exiting..."
      exit 0
    }
    
    trap exit_trap SIGTERM
    
    while true
    do
      php artisan queue:work --tries=1 --once
    done
    worker-entrypoint.sh

    ここでのポイントは --once フラグです。このフラグをつける事で worker process は 1 つの job の実行が終わったら終了します。このスクリプトでは job を終了して worker process が終了したら再度実行するように while loop で囲っています。

    SIGTERM を受け取ったら exit_trap により、それ以上 worker process を生成せずに終了します。

    ただしこのスクリプトについては、以下の部分については注意が必要なのでご注意ください。

    1. worker が 1 つの job の処理に 120 秒以上かけているものがあればエラーは発生してしまう可能性がある
    2. worker process は job を処理する事に起動されるので、フレームワークの bootstrap 分の処理が process を建てっぱなしにしておくよりも余計にかかる。(ただしそのおかげで逆にメモリーリークなどは気にしなくて良くなる)

    動作のイメージとしてはこのようになります。

    worker-entrypoint.sh と SIGTERM
    worker-entrypoint.sh と SIGTERM

    弊社ではこのスクリプトを worker-entrypoint.sh と命名して、ECS の Command として叩いています。

    終わりに

    Laravel の Worker を ECS Fargate で運用する際の tips について記載しました。

    この問題は Worker の Auto scale を導入して以来頭を悩ませていたのですが、スッキリと解決されて嬉しくなって記事化しました。

    最後に、DROBE では一緒にコードを書く仲間を募集しています!

    DROBE 採用情報

    ビジョン、事業内容、メンバー紹介など

    info.drobe.co.jp

    DROBE 採用情報

    少しでも気になった方は気軽に 応募、DM などでお知らせください!

    JavaScript is not available.

    twitter.com

    JavaScript is not available.

    参考資料

    gracefully stop php laravel sqs worker in Docker on ECS Fargate

    Using AWS SQS to process asynchronous messages is a great way to handle scheduled jobs, and work that doesn't need to happen in real-time inside your user driven application. Containerizing a PHP Laravel app and using an orchestration service like ECS Fargate allows you to easily run thousands of job queue workers in an infinite and embarrassingly parallel fashion.

    fordodone.com

    gracefully stop php laravel sqs worker in Docker on ECS Fargate
    Graceful shutdowns with ECS | Amazon Web Services

    Introduction Amazon Elastic Container Service (Amazon ECS) gives customers the flexibility to scale their containerized deployments in a variety of different ways. Tasks can be scaled-out to react to an influx of requests or they can be scaled-in to reduce cost. ECS also supports different deployment options, including rolling deployments, blue/green deployments, and canary-style deployments.

    aws.amazon.com

    Graceful shutdowns with ECS | Amazon Web Services
    Laravel - The PHP Framework For Web Artisans

    While building your web application, you may have some tasks, such as parsing and storing an uploaded CSV file, that take too long to perform during a typical web request. Thankfully, Laravel allows you to easily create queued jobs that may be processed in the background.

    laravel.com

    Laravel - The PHP Framework For Web Artisans

    © 2025 DROBE All rights reserved.