PHPはQPMを用いてマルチプロセス並列タスク処理プログラムを実現する


PHPを用いて以下のシナリオを実現することを考慮する:1つのキャプチャ局のURLリストがキューに保存され、バックグラウンドプログラムがこのキューを読み取り、サブプロセスに渡してHTMLをキャプチャしてファイルに保存する.効率を向上させるためにマルチタスクの並列実行を許可したが,マシン負荷が高すぎることを避けるために最大の並列タスク数を制限し(テストの便宜上,この数を3に設定した),キューからENDタグを取り出すとプログラムは実行を終了する.
このシーンはQPMのSupervisor::taskFactoryMode()で実現され、とても簡単です.
QPMフルネームはQuick Process Management Module for PHP.PHPは強力なweb開発言語であり、PHPが頑丈なコマンドライン(CLI)プログラムを開発してdaemonプログラムを開発することができることを忘れがちである.daemonプログラムを書くことは各種プロセス管理と付き合うことが避けられない.QPMが正式にプロセス管理を簡略化するために開発したクラスライブラリである.QPMのプロジェクトアドレスは:https://github.com/Comos/qpm
テスト環境を簡素化するために、キューのデータをテキストファイルでシミュレートできます.完全な例ファイルはここを見てください:spider_task_factory_data.txt
http://ent.ifeng.com/
http://news.sina.com.cn/
http://news.ifeng.com/
http://news.163.com/
http://news.sohu.com/
http://ent.sina.com.cn/
http://ent.ifeng.com/
...
END

QPMのtaskFactoryModeを使用する前に、TaskFactoryクラスを用意する必要があります.SpiderTaskFactory,SpdierTaskFactoryという名前のファクトリメソッドfetchTaskはRunnableのサブクラスのインスタンスを正常に返します.ENDまたはファイルが終了すると、throw StopSignalはプログラムを終了します.
以下に、Supervisorを組み立てて実行するコードクリップを示します.完全な例はspider_を参照してください.task_factory.php
//           , spider_task_factory_data.txt     

$input = isset($argv[1]) ? $argv[1] : __DIR__.'/spider_task_factory_data.txt';
$spiderTaskFactory = new SpiderTaskFactory($input);$config = [
    //  taskFactory       
    'factoryMethod'=>[$spiderTaskFactory, 'fetchTask'],
    //         3
    'quantity' => 3,
];
//  Supervisor
qpm\supervisor\Supervisor::taskFactoryMode($config)->start();

SpiderTaskFactoryの実現は以下の通りである.
/**
 *     ,     fetchTask  。
 *        
 * 
*/class SpiderTaskFactory {
    private $_fh;
    public function __construct($input) {
        $this->_input = $input;
        $this->_fh = fopen($input, 'r');
        if ($this->_fh === false) {
            throw new Exception('fopen failed:'.$input);
        }
    }
    public function fetchTask() {
      while (true) {
        if (feof($this->_fh)) {
                throw new qpm\supervisor\StopSignal();
        }
        $line = trim(fgets($this->_fh));
        if ($line == 'END') {
            throw new qpm\supervisor\StopSignal();
        }
        if (empty($line)) {
            continue;
        }
        break;
      }
      return new SpiderTask($line);
    }
}

SpiderTaskの実現は以下の通りである.
/**
 *            
 *      qpm\process\Runnable   
 */
 class SpiderTask implements qpm\process\Runnable {
    private $_target;
    public function __construct($target) {
      $this->_target = $target;
    }
    
    //          
    public function run() {
      $r = @file_get_contents($this->_target);    
      if ($r===false) {        
        throw new Exception('fail to crawl url:'.$this->_target);
      }
      file_put_contents($this->getLocalFilename(), $r);   
    }
    private function getLocalFilename() {
      $filename = str_replace('/', '~', $this->_target);    
      $filename = str_replace(':', '_', $filename);    
      $filename = $filename.'-'.date('YmdHis');    
      return __DIR__.'/_spider/'.$filename.'.html';
    }
}

実際の生産環境では、ファイル入力をキューに置き換えることで、永続的に実行される生産者/消費者モデルのプログラムを実現できます.
QPMの使用については、以下を参照してください.
QPM紹介
PHPプロセス管理フレームワークQPMのインストールと使用
qpmを使用してdaemonプログラムを作成する
QPMを使用してPHPマルチプロセスプログラムを作成する
PHPはQPMを用いてマルチプロセス並列タスク処理プログラムを実現する