swoole_processがプロセス・プールを実現する方法の例
6683 ワード
swoole――PHPの再定義
swooleのプロセスの間には2つの通信方式があります。一つはメッセージ・キュー(queue)、もう一つはパイプ(pipe)、対swoole(u)です。processの研究は特に重要です。
予備知識
IO多重化
swooleにおけるio多重化は下地層のepollプロセスモデルとして表現され,C言語ではepoll関数として表現された。 epollモデルの下で、自分の名義のsocket記述子fd を継続的に監督します。によって、socket傍受イベントがトリガされると、epoll関数は応答し、この時間を傍受するすべてのsocketセット に戻る。 epollの本質はIOをブロックすることです。その利点は同僚が大量のsocket接続 を処理できることです。
イベントループ
swooleはepollに対してReactorスレッドモデルのパッケージを実現し、readイベントとwriteイベントのモニターコールバック関数を設定しました。詳しくはswoole_を参照してくださいイベントadd) Event loopはReactorスレッドであり、ここではepollのインスタンスが実行されている。 swoole_を通過します。イベントaddは、socket記述子のイベントをepoll傍受に追加し、イベント発生時にはコールバック関数 を実行する。は、fpmがタスク終了時にプロセスをオフにする可能性があるので、fpm環境では使用できません。 swoole_process C言語パッケージに基づくプロセス管理モジュールは、便利phpにより を起動する。はパイプ、メッセージ・キュー・インターフェースを内蔵し、プロセス間通信 を容易にする。
php-fpm.co nfプロファイルでは、php-fpmには2つのプロセスプール管理設定があることを発見しました。静止モードは、固定プロセス数を初期化し、要求が来たときに、プロセスを選択して処理する。 ダイナミックモードは、要求量が大きすぎて、プロセス数が最大制限を超えない場合、スレッド処理要求 を追加する。
次にswooleコードで実現します。ここはswoole_を理解するためだけです。プロcess、プロセス間通信、タイマーなどが使用されていますが、実際にはパッケージされたswoole_を使用しています。serverはtaskタスクキュープールを実現するのに便利です。
定時配達のジョブ待ち行列がある場合:
swooleのプロセスの間には2つの通信方式があります。一つはメッセージ・キュー(queue)、もう一つはパイプ(pipe)、対swoole(u)です。processの研究は特に重要です。
予備知識
IO多重化
swooleにおけるio多重化は下地層のepollプロセスモデルとして表現され,C言語ではepoll関数として表現された。
イベントループ
swooleはepollに対してReactorスレッドモデルのパッケージを実現し、readイベントとwriteイベントのモニターコールバック関数を設定しました。詳しくはswoole_を参照してくださいイベントadd)
php-fpm.co nfプロファイルでは、php-fpmには2つのプロセスプール管理設定があることを発見しました。
次にswooleコードで実現します。ここはswoole_を理解するためだけです。プロcess、プロセス間通信、タイマーなどが使用されていますが、実際にはパッケージされたswoole_を使用しています。serverはtaskタスクキュープールを実現するのに便利です。
定時配達のジョブ待ち行列がある場合:
<?php
/**
* , fpm
*
* , , ,
*/
//
/**
* 1. tick
* 2. process
* 3. event loop
*/
class processPool
{
private $pool;
/**
* @var swoole_process[] worker process
*/
private $workers = [];
/**
* @var array worker
*/
private $used_workers = [];
/**
* @var int
*/
private $min_woker_num = 5;
/**
* @var int
*/
private $start_worker_num = 10;
/**
* @var int
*/
private $max_woker_num = 20;
/**
*
* @var int
*/
private $idle_seconds = 5;
/**
* @var int
*/
private $curr_num;
/**
*
* @var array
*/
private $active_time = [];
public function __construct()
{
$this->pool = new swoole_process(function () {
// worker
for ($i = 0; $i < $this->start_worker_num; $i++) {
$this->createWorker();
}
echo ' :' . $this->curr_num . PHP_EOL;
// worker
swoole_timer_tick(1000, function ($timer_id) {
static $count = 0;
$count++;
$need_create = true;
foreach ($this->used_workers as $pid => $used) {
if ($used == 0) {
$need_create = false;
$this->workers[$pid]->write($count . ' job');
//
$this->used_workers[$pid] = 1;
$this->active_time[$pid] = time();
break;
}
}
foreach ($this->used_workers as $pid => $used)
// worker , worker
if ($need_create && $this->curr_num < $this->max_woker_num) {
$new_pid = $this->createWorker();
$this->workers[$new_pid]->write($count . ' job');
$this->used_workers[$new_pid] = 1;
$this->active_time[$new_pid] = time();
}
//
foreach ($this->active_time as $pid => $timestamp) {
if ((time() - $timestamp) > $this->idle_seconds && $this->curr_num > $this->min_woker_num) {
//
if (isset($this->workers[$pid]) && $this->workers[$pid] instanceof swoole_process) {
$this->workers[$pid]->write('exit');
unset($this->workers[$pid]);
$this->curr_num = count($this->workers);
unset($this->used_workers[$pid]);
unset($this->active_time[$pid]);
echo "{$pid} destroyed
";
break;
}
}
}
echo " {$count}/{$this->curr_num}
";
if ($count == 20) {
foreach ($this->workers as $pid => $worker) {
$worker->write('exit');
}
//
swoole_timer_clear($timer_id);
//
$this->pool->exit(0);
exit();
}
});
});
$master_pid = $this->pool->start();
echo "Master $master_pid start
";
while ($ret = swoole_process::wait()) {
$pid = $ret['pid'];
echo "process {$pid} existed
";
}
}
/**
*
* @return int pid
*/
public function createWorker()
{
$worker_process = new swoole_process(function (swoole_process $worker) {
//
swoole_event_add($worker->pipe, function ($pipe) use ($worker) {
$data = trim($worker->read());
if ($data == 'exit') {
$worker->exit(0);
exit();
}
echo "{$worker->pid} {$data}
";
sleep(5);
// ,
$worker->write("complete");
});
});
$worker_pid = $worker_process->start();
//
swoole_event_add($worker_process->pipe, function ($pipe) use ($worker_process) {
$data = trim($worker_process->read());
if ($data == 'complete') {
//
// echo "{$worker_process->pid}
";
$this->used_workers[$worker_process->pid] = 0;
}
});
// process
$this->workers[$worker_pid] = $worker_process;
//
$this->used_workers[$worker_pid] = 0;
$this->active_time[$worker_pid] = time();
$this->curr_num = count($this->workers);
return $worker_pid;
}
}
new processPool();
以上が本文の全部です。皆さんの勉強に役に立つように、私たちを応援してください。