43

私は多くの Gearman ワーカーを常に実行しており、ユーザー ページ ビューの記録などを保存しています。ときどき、Gearman ワーカーが使用する PHP コードを更新します。ワーカーを新しいコードに切り替えるために、ワーカーの PHP プロセスを強制終了して再起動します。

これを行うためのより良い方法は何ですか? おそらく、これらのワーカー プロセスの 1 つを強制終了すると、(それほど重要なデータではありませんが) データが失われることがあります。

編集:私に合った答えを見つけて、以下に投稿しました。

4

12 に答える 12

12

解決策 1


通常、私は -r フラグを指定して unix デーモン ユーティリティを使用してワーカーを実行し、1 つのジョブの後に期限切れにします。スクリプトは反復ごとに正常に終了し、デーモンは自動的に再起動します。

ワーカーは 1 つのジョブで古くなりますが、それはデータを失うことほど大したことではないかもしれません

このソリューションには、メモリを解放できるという利点もあります。PHP 5.3 より前の GC にはひどい GC があるため、大規模なジョブを実行している場合、メモリに問題が発生する可能性があります。

解決策 2


スクリプトを終了するすべてのワーカーに quit 関数を追加することもできます。再起動したい場合は、ギアマンに高い優先度で終了するように呼びかけるだけです。

于 2010-03-23T14:36:37.940 に答える
8
function AutoRestart() {
   static $startTime = time();

   if (filemtime(__FILE__) > $startTime) {
      exit();
   }
}

AutoRestart();  
于 2011-08-17T08:05:46.987 に答える
7

さて、私はこの質問を投稿しました、今私はそれに良い答えを見つけたと思います。

Net_Gearman_Workerのコードを見ると、作業ループで関数stopWorkが監視されており、trueが返された場合は、関数が終了していることがわかります。

次のことを行い
ました。memcacheを使用して、キャッシュされた値gearman_restarttimeを作成し、別のスクリプトを使用して、サイトを更新するたびに現在のタイムスタンプに設定しました。(私はMemcacheを使用しましたが、これはデータベース、ファイルなど、どこにでも保存できます)。

私はWorkerクラスを基本的にNet_Gearman_Worker_Fooに拡張し、すべてのワーカーにそれをインスタンス化させました。Fooクラスでは、stopWork関数をオーバーライドして、次のことを行います。まず、gearman_restarttimeをチェックします。初めて、値をグローバル変数に保存します。それ以降、毎回、キャッシュされた値をグローバルと比較します。変更された場合、stopWorkはtrueを返し、ワーカーは終了します。cronは毎分チェックして、各ワーカーがまだ実行されているかどうかを確認し、終了したワーカーを再起動します。

stopWorkにもタイマーを設定し、x分ごとに1回だけキャッシュをチェックすることをお勧めします。私たちの場合、Memcacheは十分に高速なので、毎回値をチェックすることは問題ではないようですが、他のシステムを使用して現在のタイムスタンプを保存している場合は、チェックの頻度を減らす方がよいでしょう。

于 2010-06-09T19:33:22.813 に答える
1

http://phpscaling.com/2009/06/23/doing-the-work-elsewhere-sidebar-running-the-worker/

上記の記事が示すように、私はBASHシェルスクリプト内でワーカーを実行し、クリーンアップ(またはworker-scriptを再ロード)するためにジョブ間で時々終了します-または、特定のタスクが与えられた場合、特定のタスクで終了できます終了コードとシャットダウンします。

于 2010-03-03T13:18:45.020 に答える
1

私も最近これを見てきました (ただし、Gearman::XS を使用した perl で)。私のユースケースはあなたのものと同じでした - 長時間稼働しているギアマンワーカーが定期的に新しいバージョンをチェックしてリロードできるようにします。

私の最初の試みは、ワーカー スクリプトのバージョンを最後にチェックしてからの時間をワーカーに追跡させることでした (md5sum も機能します)。次に、ジョブ間で N 秒が経過すると、それ自体の新しいバージョンが利用可能かどうかを確認し、それ自体を再起動します (fork()/exec())。これは問題なく機能しましたが、まれなジョブに登録されたワーカーは、work() が返されるまで何時間も待たされる可能性があり、したがって現在の時刻を確認する必要がありました。

そのため、work() でジョブを待機するときのタイムアウトをかなり短く設定しているので、時間をより定期的に確認できます。PHP インターフェイスは、ジョブの登録時にこのタイムアウト値を設定できることを示唆しています。SIGALRM を使用して新しいバージョンのチェックをトリガーしています。perl インターフェイスが work() でブロックされるため、最初はアラームがトリガーされませんでした。タイムアウトを 60 秒に設定すると、SIGALRM が機能しました。

于 2010-06-03T10:34:01.773 に答える
1

うーん、ワーカーにコードを実装して、ソース コードが変更されているかどうかを時折チェックすることができます。つまり、ジョブの途中で、ジョブが非常に大きいかどうかを確認します。

他の方法は、何らかの割り込みを実装することです。ネットワークを介して、機会があればいつでも停止して再起動することができます。

最後の解決策は、Gearman のソースを変更してこの機能を含めることです。

于 2010-02-16T20:36:27.800 に答える
1

ワーカーが PHP で記述されているという事実を考えると、既知のスケジュールでワーカーをリサイクルすることをお勧めします。これは、開始されてからの静的な時間である場合もあれば、一定数のジョブが試行された後に実行される場合もあります。

これは本質的に一石二鳥です(しゃれた意図はありません)。メモリ リークの可能性を軽減しており、潜在的に新しいコードをいつワーカーが取得するかを判断するための一貫した方法があります。

私は通常、ワーカーがプロセスのどこにいるかを簡単に確認できるように、ワーカーがその間隔を stdout やログ機能に報告するように記述します。

于 2011-03-28T23:00:58.480 に答える
1

誰かが perl を実行しているワーカーの答えを探していた場合、それはGearmanX::Starterライブラリの目的の一部です。現在のジョブの完了後にワーカーを停止するには、2 つの異なる方法があります。ワーカー プロセスに SIGTERM を外部的に送信する方法と、プログラムでグローバル変数を設定する方法です。

于 2010-08-12T18:40:54.130 に答える
0

これは、継続的インテグレーション システムにうまく適合します。私はあなたがそれを持っていることを願っています:-)

新しいコードをチェックインすると、自動的にビルドされてサーバーにデプロイされます。ビルド スクリプトの一部として、すべてのワーカーを強制終了し、新しいワーカーを起動します。

于 2010-02-16T21:12:52.483 に答える