「労働者が自分の仕事をうまくやりたいなら、まず自分の道具を研ぎ澄まさなければなりません。」 - 孔子、「論語。陸霊公」
表紙 > プログラミング > スーパーバイザーを使用して Symfony コマンドの実行を処理する

スーパーバイザーを使用して Symfony コマンドの実行を処理する

2024 年 11 月 1 日に公開
ブラウズ:387

導入

この投稿では、supervisord を使用して symfony コマンドの実行を処理する方法を学びます。基本的に、supervisord では次のことが可能になります:

  • コマンドを自動開始します
  • コマンドを自動再起動します
  • スーパーバイザーに開始させるプロセスの数を指定します。

問題

プロセスの実行を自動化するために、UNIX の crontab を利用することがあります。ほとんどの場合これで機能しますが、問題が発生する可能性があります。

ユーザーの通知を記録するデータベース テーブルがあると想像してみましょう。テーブルには次の情報が保存されます:

  • ユーザー
  • 文章
  • チャネル
  • ステータス (待機中、送信済み)
  • 作成場所
  • 更新日時

一方、次のステップに従って実行されるコマンドをコーディングしました:

  • 最後の待機通知をクエリします
  • クエリされた通知をループし、次の処理を行います。
    • それぞれを対応するユーザーに送信します。
    • 通知ステータスを待機中から送信済みに更新します

Linux crontab でこのコマンドを頻繁に (1 分、2 分など) 実行するように設定しました。ここまでは順調ですね。

次に、現在のプロセスが 500 件の通知をクエリし、400 件を送信したときに新しいプロセスが開始すると想像してみましょう。これは、新しいプロセスが、最後のプロセスによってまだ更新されていない 100 件の通知と新しい通知をクエリすることを意味します:

Using Supervisor to handle a Symfony Command execution

これにより、両方のプロセスがクエリを実行したため、これらの 100 件の通知が 2 回送信される可能性があります。

解決策

解決策として、スーパーバイザーを使用することができます。これによりプロセスが実行され続け、必要に応じて再起動されます。このようにして、プロセスを 1 つだけ保持し、重複を避けます。コマンドがどのように見えるかを分析してみましょう:

#[AsCommand(
    name: 'app:notification'
)]
class NotificationCommand extends Command
{
    private bool $forceFinish = false;

    protected function configure(): void
    {
        $this
            ->addOption('time-limit', null, InputOption::VALUE_OPTIONAL, 'Max time alive in seconds')
            ->addOption('time-between-calls', null, InputOption::VALUE_OPTIONAL, 'Time between every loop call')

        ;
    }

    protected function execute(InputInterface $input, OutputInterface $output): int
    {
        $this->forceFinish = false;
        pcntl_signal(SIGTERM, [$this, 'signalHandler']);
        pcntl_signal(SIGINT, [$this, 'signalHandler']);

        $timeLimit = $input->getOption('time-limit');
        $timeBetweenCalls = $input->getOption('time-between-calls');
        $dtMax = (new \DateTimeImmutable())->add(\DateInterval::createFromDateString("  {$timeLimit} seconds"));

        do{
           // Here we should execute a service to query and send notifications
           // ......

           sleep($timeBetweenCalls);
           $dtCurrent = new \DateTimeImmutable();

        }while($dtCurrent forceFinish);

        return Command::SUCCESS;
    }

    public function signalHandler(int $signalNumber): void
    {
        echo 'Signal catch: ' . $signalNumber . PHP_EOL;
        match ($signalNumber) {
            SIGTERM, SIGINT => $this->forceFinish = true,
            default => null
        };
    }
}

コマンドをステップバイステップで説明しましょう:

  • configure メソッドは、オプションを入力することを宣言します:

    • time-limit: コマンド プロセスが存続できる最大時間。その後、終了し、スーパーバイザーが再起動します。
    • time-between-calls: 各ループ反復後のスリープ時間。このループは、通知を処理するサービスを呼び出し、その間はスリープします。
  • execute メソッドは次のように動作します:

    • forceFinish クラス変数を true に設定します
    • PHP pnctl ライブラリを使用して、Unix SIGTERM および SIGINT シグナルを処理するためのメソッド signalHandler を登録します。
    • 入力オプション値を取得し、time-limit オプション値を使用するまでコマンドが有効である最大日付を計算します。
    • do-while ループは、通知を取得して送信するために必要なコードを実行します (コマンドには配置されず、代わりにコメントがあります)。その後、続行する前に、time-between-calls オプションで設定された時間スリープします。
    • 現在の日付 (ループ反復ごとに計算されます) が最大日付より小さく、forceFinish が false の場合、ループは継続します。それ以外の場合、コマンドは終了します。
  • signalHandler 関数は、SIGTERM および SIGINT Unix シグナルをキャッチします。 SIGINT は Ctrl C を押したときに送信されるシグナルであり、SIGTERM は kill コマンドを使用するときのデフォルトのシグナルです。 signalHandler 関数がそれらを検出すると、forceFinish 変数を true に設定します。これにより、forceFinish 変数は次のとおりであるため、現在のループが終了するとコマンドが終了します。もはや偽りではありません。これにより、ユーザーは最大日付が終了するまで待つことなくプロセスを終了できます。

スーパーバイザの構成

ここまででコマンドが作成されました。次に、スーパーバイザがそれを処理できるようにセットアップします。設定を始める前に、スーパーバイザをインストールする必要があります。次のコマンドを実行して実行できます:

sudo apt update && sudo apt install supervisor

インストール後、次のコマンドを実行することでスーパーバイザが実行されていることを確認できます:

sudo systemctl status supervisor

スーパーバイザー設定ファイルは、/etc/supervisor/conf.d フォルダーに配置されます。 notif.conf という名前のファイルを作成し、次の内容を貼り付けましょう:

command=php /bin/console app:notifications --time-limit=120 --time-between-calls=10
user=
numprocs=1
autostart=true
autorestart=true
process_name=%(program_name)s_%(process_num)02d

各キーについて説明しましょう:

  • command: 開始するコマンド
  • user: コマンドを実行する UNIX ユーザー
  • numprocs: 実行するプロセスの数
  • autostart: コマンドを自動起動するかどうか
  • autostart: コマンドを自動再起動するかどうか
  • process_name: コマンド unix プロセス名の形式。

この設定では、app:notifications コマンドは最大 120 秒間実行され、ループごとに 10 秒間スリープします。 120 秒が経過するか、UNIX シグナルをキャッシュした後、コマンドはループを抜けて終了します。その後、スーパーバイザーが再度開始します。

結論

スーパーバイザーを使用して、crontab を使用せずにコマンドを実行し続ける方法を学びました。これは、crontab によって起動されたプロセスが重複してデータ破損を引き起こす可能性がある場合に役立ちます。

私が書いた最後の本では、スーパーバイザーを使用して symfony メッセンジャーワーカーを実行し続ける方法を示しました。さらに詳しく知りたい場合は、次の書籍を参照してください: PHP と Symfony フレームワークを使用した操作指向の API の構築: ステップバイステップ ガイド

リリースステートメント この記事は次の場所に転載されています: https://dev.to/icolomina/using-supervisor-to-handle-a-symfony-command-execution-41h7?1 侵害がある場合は、[email protected] に連絡して削除してください。それ
最新のチュートリアル もっと>
  • Java の配列の概要
    Java の配列の概要
    プログラミングでは多くの場合、大規模なデータセットの管理と操作が必要となるため、効率的かつ効果的なデータ構造が重要です。配列はコンピューター サイエンスの基本的なデータ構造であり、同じタイプの要素の固定サイズのシーケンスを格納する手段を提供します。このブログでは、Java の配列について詳しく説明し...
    プログラミング 2024 年 11 月 7 日に公開
  • CORS 問題を解決する方法
    CORS 問題を解決する方法
    CORS 問題を解決するには、Web サーバー (Apache や Nginx など) またはバックエンド (Django、Go、Node.js など) に適切なヘッダーを追加する必要があります。 、またはフロントエンド フレームワーク (React や Next.js など)。以下は各プラットフォ...
    プログラミング 2024 年 11 月 7 日に公開
  • メモリのアライメントは C 構造体のサイズにどのような影響を与えますか?
    メモリのアライメントは C 構造体のサイズにどのような影響を与えますか?
    C 構造体のメモリ アライメントC 構造体を扱う場合、メモリ アライメントを理解することが重要です。メモリの配置とは、メモリ内の特定の境界にデータを配置することを指します。 32 ビット マシンでは、メモリは通常 4 バイト境界でアライメントされます。構造体のメモリ アライメント次の構造体を考えてみ...
    プログラミング 2024 年 11 月 7 日に公開
  • 人気の観光名所からインスピレーションを得た革新的なプロジェクトの構築: 思い出に残る旅行体験への開発者向けガイド
    人気の観光名所からインスピレーションを得た革新的なプロジェクトの構築: 思い出に残る旅行体験への開発者向けガイド
    開発者として、私たちは周囲の世界からインスピレーションを得ることはよくありますが、信じられないほどの観光名所以上に優れた情報源はあるでしょうか。旅行アプリ、没入型体験、位置情報ベースのサービスのいずれに取り組んでいる場合でも、目的地を際立たせるものを理解することが重要です。アルバニアの最高の観光名所...
    プログラミング 2024 年 11 月 7 日に公開
  • C++ で std::locale を使用して数値をカンマでフォーマットする方法
    C++ で std::locale を使用して数値をカンマでフォーマットする方法
    C でのカンマを使用した数値の書式設定 C では、 std::locale クラスは、カンマを使用して数値を書式設定するロケール依存の方法を提供します。 .std::locale with std::stringstream数値をカンマ付きの文字列としてフォーマットするには、std::locale ...
    プログラミング 2024 年 11 月 7 日に公開
  • Python で素数シーケンス内の奇数の出力を回避するには?
    Python で素数シーケンス内の奇数の出力を回避するには?
    Python で一連の素数を出力する方法多くのプログラマは、Python で素数を正確に出力する関数を作成するのに苦労しています。よくある問題の 1 つは、代わりに奇数のリストを出力することです。この問題を修正するには、素数のプロパティを完全に理解し、コードを変更することが不可欠です。素数は 1 と...
    プログラミング 2024 年 11 月 7 日に公開
  • Pygameでマウスの方向に弾丸を発射するにはどうすればよいですか?
    Pygameでマウスの方向に弾丸を発射するにはどうすればよいですか?
    Pygame でマウスの方向に弾丸を発射する方法Pygame では、マウスの方向に発射される弾丸を作成できます。これを行うには、弾丸を表すクラスを作成し、マウスの位置に基づいてその初期位置と方向を設定する必要があります。弾丸のクラスまず、弾丸のクラスを作成します。このクラスには、弾丸の位置、サイズ、...
    プログラミング 2024 年 11 月 7 日に公開
  • パフォーマンスを最適化するための GG コーディングのヒント: コードの高速化
    パフォーマンスを最適化するための GG コーディングのヒント: コードの高速化
    ソフトウェア開発の世界では、ユーザーが好む高速で応答性の高いアプリケーションを提供するには、コードのパフォーマンスを最適化することが重要です。フロントエンドで作業しているかバックエンドで作業しているかに関係なく、効率的なコードの書き方を学ぶことが不可欠です。この記事では、時間の複雑さの軽減、キャッシ...
    プログラミング 2024 年 11 月 7 日に公開
  • PHP の strtotime() 関数を使用して特定の曜日の日付を見つけるにはどうすればよいですか?
    PHP の strtotime() 関数を使用して特定の曜日の日付を見つけるにはどうすればよいですか?
    特定の曜日(月曜日、火曜日など)の日付を決定する日付スタンプを確認する必要がある場合月曜日、火曜日、その他の平日など、特定の曜日には strtotime() 関数を使用できます。この関数は、今週中に指定された日がまだ発生していない場合に特に便利です。たとえば、次の火曜日の日付スタンプを取得するには、...
    プログラミング 2024 年 11 月 7 日に公開
  • Socket.io と Redis を使用してチャット アプリケーションを構築し、デプロイします。
    Socket.io と Redis を使用してチャット アプリケーションを構築し、デプロイします。
    このチュートリアルでは、Web ソケットを使用してチャット アプリケーションを構築します。 Web ソケットは、リアルタイムのデータ転送を必要とするアプリケーションを構築する場合に非常に役立ちます。 このチュートリアルを終えると、独自のソケット サーバーをセットアップし、リアルタイムでメッセージを送...
    プログラミング 2024 年 11 月 7 日に公開
  • 内部 SQL 結合
    内部 SQL 結合
    SQL 結合はデータベースのクエリの基本であり、ユーザーは指定された条件に基づいて複数のテーブルのデータを結合できます。結合は、論理結合と物理結合の 2 つの主なタイプに分類されます。論理結合はテーブルのデータを組み合わせる概念的な方法を表し、物理結合は RDS (リレーショナル データベース サー...
    プログラミング 2024 年 11 月 7 日に公開
  • 知っておくべきJavaScriptの機能
    知っておくべきJavaScriptの機能
    この記事では、未定義または null の可能性があるデータにアクセスしようとするときにエラーを防ぐ方法を検討し、できる方法を見ていきます。 必要に応じてデータを効果的に管理するために使用します. オプションのチェーンによる安全なアクセス JavaScript で、入れ子になったオブジ...
    プログラミング 2024 年 11 月 7 日に公開
  • JavaScript の約束: 非同期コードの理解、処理、および習得
    JavaScript の約束: 非同期コードの理解、処理、および習得
    イントロ 私は Java 開発者として働いていましたが、JavaScript の Promise に初めて触れたときのことを覚えています。コンセプトは単純そうに見えましたが、Promise がどのように機能するのかを完全に理解することはできませんでした。プロジェクトでそれらを使用し...
    プログラミング 2024 年 11 月 7 日に公開
  • パスキーを Java Spring Boot に統合する方法
    パスキーを Java Spring Boot に統合する方法
    Java Spring Boot のパスキーの概要 パスキーは、従来のパスワードに依存せずにユーザーを認証する最新の安全な方法を提供します。このガイドでは、Thymeleaf をテンプレート エンジンとして使用して、Java Spring Boot アプリケーションにパスキーを統合...
    プログラミング 2024 年 11 月 7 日に公開
  • グアテマラの前環境大臣としてのマリオ・ロベルト・ロハス・エスピノの影響
    グアテマラの前環境大臣としてのマリオ・ロベルト・ロハス・エスピノの影響
    マリオ・ロベルト・ロハス・エスピノはグアテマラの元環境大臣として、国の持続可能な発展に貢献した環境政策の実施において重要な役割を果たしました。同省長官としての彼の経営は、特に環境立法や保全プロジェクトの面で重要な遺産を残した。この記事では、彼の影響力と、任期中に彼が推進した主な政策について探ります。...
    プログラミング 2024 年 11 月 7 日に公開

免責事項: 提供されるすべてのリソースの一部はインターネットからのものです。お客様の著作権またはその他の権利および利益の侵害がある場合は、詳細な理由を説明し、著作権または権利および利益の証拠を提出して、電子メール [email protected] に送信してください。 できるだけ早く対応させていただきます。

Copyright© 2022 湘ICP备2022001581号-3