Symfony Commonmand Duplicate Lock

画像



今日は、前のプロセスがまだ完了していない場合のプロセスの定期的な起動に関連する「不便さ」を解決するための特別なケースに注目したいと思います。 言い換えると、 symfony / consoleで実行中のプロセスをブロックします。 しかし、単一のサーバーではなく、サーバーのグループ間でブロックする必要がなければ、すべてが平凡になります。



指定: Nサーバーで実行される同じプロセス。

タスク:時間単位ごとに1つだけが開始されるようにします。



「オープンスペース」にある最も人気のあるソリューション:



  1. データベースをロックします。
  2. サードパーティアプリケーション。
  3. ロックファイルのネイティブ使用


それぞれの主な欠点:



データベース





サードパーティアプリケーション(Ubuntu用のrun-oneなど)





ネイティブロックファイル





もちろん、最も一般的なのは3番目のオプションですが、多数のサーバーとプロセスが存在する場合、多くの不便が生じます。 それで、 シングルトン symfony /コンソールベースのコマンドを書くというアイデアを共有することにしました。 しかし、このアイデアは他のフレームワークで使用できます。



そのため、最初に放棄しなければならなかったのはflock でした 。これは、たとえばsymfonyの LockHandlerで使用されます。 複数のサーバー間でブロックすることはできません。



代わりに、小さなサービスを使用して、サーバー間で共有されるディレクトリにロックファイルを作成します。これは実質的にLockHandlerに類似していますが、「sawn out」 flockを備えています。



次に取り除くべきことは、各チームがロックを手動でチェックする必要があることです。最も重要なことは、ロックは想定した場所で終わるとは限らないためです。



これを行うには、Mediatorに似たものを使用することを提案します。標準のexecute()メソッドを実装および終了します。



これは何のためですか:





結果として、標準のsymfonyコマンド:



class CreateUserCommand extends Command { protected function configure() { // ... } protected function execute(InputInterface $input, OutputInterface $output) { // ... } }
      
      





次のようになります。



 class CreateUserCommand extends SingletonCommand implements SingletonCommandInterface { protected function configure() { // ... } public function lockExecute(InputInterface $input, OutputInterface $output) { // ... } }
      
      





さらに多くのコードを記述する必要はありませんが、同時に、いくつのサーバーがこれを実行しようとしても、1回だけ実行されることが保証されます。 唯一の条件は、ロックファイルの共有ディレクトリです。



既製のソリューションと詳細はgithubにあります: singleton-command



UPD:当然のことながら、「ハード」スクリプトがクラッシュした場合、ロックファイルを保存できます。 したがって、「古い」ロックファイルを「監視」するデーモンを編成することをお勧めします。



ご清聴ありがとうございました!



All Articles