2009-04-15 14 views
14

問題:非同期ジョブ用のMQサーバーキューをリッスンしているいくつかのPHPワーカープロセスを実装したいと思います。問題は今、単にこのプロセスをサーバー上のデーモンとして実行しても、実際にps -auxをダンプする場合を除いて、インスタンス(Load、Status、locked up)を制御することはできません。 システム(プロセス)レベルまたは上位層(Javaスタイルのアプリケーションサーバーのようなもの)で、インスタンスを監視して制御できるようなランタイム環境を探しています。PHPデーモン/ワーカー環境

Anyポインタ?

+0

も参照してください:http://symfony.com/doc/master/components/process.htmlは –

答えて

12

有用なコードがいくつかあります。

<? 
define('WANT_PROCESSORS', 5); 
define('PROCESSOR_EXECUTABLE', '/path/to/your/processor'); 
set_time_limit(0); 
$cycles = 0; 
$run = true; 
$reload = false; 
declare(ticks = 30); 

function signal_handler($signal) { 
    switch($signal) { 
    case SIGTERM : 
     global $run; 
     $run = false; 
     break; 
    case SIGHUP : 
     global $reload; 
     $reload = true; 
     break; 
    } 
} 

pcntl_signal(SIGTERM, 'signal_handler'); 
pcntl_signal(SIGHUP, 'signal_handler'); 

function spawn_processor() { 
    $pid = pcntl_fork(); 
    if($pid) { 
     global $processors; 
     $processors[] = $pid; 
    } else { 
     if(posix_setsid() == -1) 
      die("Forked process could not detach from terminal\n"); 
     fclose(stdin); 
     fclose(stdout); 
     fclose(stderr); 
     pcntl_exec(PROCESSOR_EXECUTABLE); 
     die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n"); 
    } 
} 

function spawn_processors() { 
    global $processors; 
    if($processors) 
     kill_processors(); 
    $processors = array(); 
    for($ix = 0; $ix < WANT_PROCESSORS; $ix++) 
     spawn_processor(); 
} 

function kill_processors() { 
    global $processors; 
    foreach($processors as $processor) 
     posix_kill($processor, SIGTERM); 
    foreach($processors as $processor) 
     pcntl_waitpid($processor); 
    unset($processors); 
} 

function check_processors() { 
    global $processors; 
    $valid = array(); 
    foreach($processors as $processor) { 
     pcntl_waitpid($processor, $status, WNOHANG); 
     if(posix_getsid($processor)) 
      $valid[] = $processor; 
    } 
    $processors = $valid; 
    if(count($processors) > WANT_PROCESSORS) { 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      posix_kill($processors[$ix], SIGTERM); 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      pcntl_waitpid($processors[$ix]); 
    } elseif(count($processors) < WANT_PROCESSORS) { 
     for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++) 
      spawn_processor(); 
    } 
} 

spawn_processors(); 

while($run) { 
    $cycles++; 
    if($reload) { 
     $reload = false; 
     kill_processors(); 
     spawn_processors(); 
    } else { 
     check_processors(); 
    } 
    usleep(150000); 
} 
kill_processors(); 
pcntl_wait(); 
?> 
+0

あなたはこれをどこで買いましたの?オープンソースのプロジェクトか独自のコード?正確にここで何が起こっているのかの説明や説明はありますか? – leek

+0

私のコードです。私はそれを説明するつもりはない、いいえ。 – chaos

+0

また、https://github.com/kvz/system_daemon。 – HyderA

1

実際に連続して実行する必要がありますか?

新しいプロセスを要求に応じて作成する場合は、xinetdでサービスとして登録することができます。

+0

労働者の数は通常は一定のシステム性能に依存しているため、産卵面は大きな問題ではありません。より重要なことは、個々の労働者の状態(クラッシュ、何でも)を監視することです。私が今発見したツールの1つは、DJBs deamontools – Sebastian

+0

です。監視のために、flock()で作成したPIDファイルを使用することもできます。クラッシュすると、すべてのロックが解除されます。 – vartec

4

すでにMQを稼働していて、* nixシステム上で稼動しているというだけで、作業者を管理する方法が必要です。

非常に簡単な方法は、GNU screenを使うことです。 10人の労働者を起動するには、使用することができます。これは、そうでworker_1,2,3という名前の画面を使用してバックグラウンドで10人の労働者を起動します

#!/bin/sh 
for x in `seq 1 10` ; do 
screen -dmS worker_$x php /path/to/script.php worker$x 
end 

screen -r worker_を実行してscreenに再接続し、screen-listを使用して実行中のワーカーをリストすることができます。

詳細情報については、このガイドが助けになることがあります。 http://www.kuro5hin.org/story/2004/3/9/16838/14935

関連検索:

  • 画面を
  • 男性画面
  • またはgoogle --help。

プロダクションサーバーの場合、通常は通常のシステム起動スクリプトを使用することをお勧めしますが、何年も問題なく起動スクリプトから画面コマンドを実行しています。

0

ベローは@chaos答えの私たちの作業の実装であるためPCNTLプラグイン型サーバデーモン。このスクリプトは通常わずか数ミリ秒であるため、シグナルを処理するコードは削除されました。

また、コードでは、呼び出し間にpidを保存する2つの関数restore_processors_state()とsave_processors_state()を追加しました。 redisを使用しましたが、ファイルの実装を使用することができます。

このスクリプトはcronを使用して毎分実行します。 Cronはすべてのプロセスが生きているかどうかをチェックします。そうでなければ、それを再実行してから死ぬ。既存のプロセスを終了させたい場合は、引数killphp script.php killでこのスクリプトを実行するだけです。

init.dにスクリプトを挿入することなく、非常に便利な方法で作業者を実行できます。

<?php 

include_once dirname(__FILE__) . '/path/to/bootstrap.php'; 

define('WANT_PROCESSORS', 5); 
define('PROCESSOR_EXECUTABLE', '' . dirname(__FILE__) . '/path/to/worker.php'); 
set_time_limit(0); 

$run = true; 
$reload = false; 
declare(ticks = 30); 

function restore_processors_state() 
{ 
    global $processors; 

    $redis = Zend_Registry::get('redis'); 
    $pids = $redis->hget('worker_procs', 'pids'); 

    if(!$pids) 
    { 
     $processors = array(); 
    } 
    else 
    { 
     $processors = json_decode($pids, true); 
    } 
} 

function save_processors_state() 
{ 
    global $processors; 

    $redis = Zend_Registry::get('redis'); 
    $redis->hset('worker_procs', 'pids', json_encode($processors)); 
} 

function spawn_processor() { 
    $pid = pcntl_fork(); 
    if($pid) { 
     global $processors; 
     $processors[] = $pid; 
    } else { 
     if(posix_setsid() == -1) 
      die("Forked process could not detach from terminal\n"); 
     fclose(STDIN); 
     fclose(STDOUT); 
     fclose(STDERR); 
     pcntl_exec('/usr/bin/php', array(PROCESSOR_EXECUTABLE)); 
     die('Failed to fork ' . PROCESSOR_EXECUTABLE . "\n"); 
    } 
} 

function spawn_processors() { 
    restore_processors_state(); 

    check_processors(); 

    save_processors_state(); 
} 

function kill_processors() { 
    global $processors; 
    foreach($processors as $processor) 
     posix_kill($processor, SIGTERM); 
    foreach($processors as $processor) 
     pcntl_waitpid($processor, $trash); 
    unset($processors); 
} 

function check_processors() { 
    global $processors; 
    $valid = array(); 
    foreach($processors as $processor) { 
     pcntl_waitpid($processor, $status, WNOHANG); 
     if(posix_getsid($processor)) 
      $valid[] = $processor; 
    } 
    $processors = $valid; 
    if(count($processors) > WANT_PROCESSORS) { 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      posix_kill($processors[$ix], SIGTERM); 
     for($ix = count($processors) - 1; $ix >= WANT_PROCESSORS; $ix--) 
      pcntl_waitpid($processors[$ix], $trash); 
    } 
    elseif(count($processors) < WANT_PROCESSORS) { 
     for($ix = count($processors); $ix < WANT_PROCESSORS; $ix++) 
      spawn_processor(); 
    } 
} 

if(isset($argv) && count($argv) > 1) { 
    if($argv[1] == 'kill') { 
     restore_processors_state(); 
     kill_processors(); 
     save_processors_state(); 

     exit(0); 
    } 
} 

spawn_processors();