<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                [toc] ## 進程管理 ### 官網實例了解進程api 根據官方實例加上注釋 * 子進程異常退出時,自動重啟 * 主進程異常退出時,子進程會繼續執行,完成所有任務后退出 ~~~ class Process { // 主進程的pid public $mpid = 0; // public $works = []; // 創建多少個子進程 public $max_precess = 1; public $new_index = 0; public function __construct() { try { // 給當前主進程命名 swoole_set_process_name(sprintf('php-ps:%s' , 'master')); // 獲得當前主進程的PID $this->mpid = posix_getpid(); // 創建子進程并運行 $this->run(); // 運行結束后回收并重啟 $this->processWait(); } catch (\Exception $e) { die('ALL ERROR: ' . $e->getMessage()); } } public function run() { for ($i = 0;$i < $this->max_precess;$i ++) { $this->CreateProcess(); } } public function CreateProcess($index = null) { // 創建子進程,用于在檢查主進程是否還活著 $process = new \swoole_process( function (\swoole_process $worker) use ($index){ // 設置進程名稱 if (is_null($index)) { $index = $this->new_index; $this->new_index ++; } swoole_set_process_name(sprintf('php-ps:%s' , $index)); // 120秒后重啟子進程 for ($j = 0;$j < 120;$j ++) { $this->checkMpid($worker); echo "msg: {$j}\n"; sleep(1); } } , false , false ); $pid = $process->start(); $this->works[$index] = $pid; return $pid; } public function checkMpid(&$worker) { // 檢查主進程是否存在 if (!\swoole_process::kill($this->mpid , 0)) { // 如果不存在的話就退出子進程 $worker->exit(); // 這句提示,實際是看不到的.需要寫到日志中 echo "Master process exited, I [{$worker['pid']}] also quit\n"; } } public function rebootProcess($ret) { $pid = $ret['pid']; $index = array_search($pid , $this->works); if ($index !== false) { $index = intval($index); // 名稱設置為一樣 $new_pid = $this->CreateProcess($index); echo "rebootProcess: {$index}={$new_pid} Done\n"; return; } throw new \Exception('rebootProcess Error: no pid'); } public function processWait() { while (1) { // 如果子進程存在 if (count($this->works)) { // 等待其結束后回收 $ret = \swoole_process::wait(); if ($ret) { // 回收成功后重啟子進程 $this->rebootProcess($ret); } } else { break; } } } } ~~~ 使用`ps aft | grep php`查看進程關系 ![](https://i.loli.net/2019/04/26/5cc29faa3e6aa.png) ### 父子進程通過管道通信 ~~~ // 第二參數設為true,可以使用write和read來通過管道使父子進程通信 $process = new \swoole_process( function (\swoole_process $process){ $process->write('Hello'); } , true ); $process->start(); usleep(100); // 輸出 Hello echo $process->read(); ~~~ ### 調用外部程序 ~~~ $process = new \Swoole\Process( function (\Swoole\Process $childProcess){ // 1. 必須寫絕對路徑 // 2. 參數必須分開放到數組中 $childProcess->exec( '/usr/local/bin/php' , [ '/var/www/project/yii-best-practice/cli/yii' , 't/index' , '-m=123' , 'abc' , 'xyz' ]); // 3. 執行shell命令,略有區別。不過一般使用協程co:exec() $childProcess->exec('/bin/sh' , ['-c' , "cp -rf /data/test/* /tmp/test/"]); } ); $process->start(); ~~~ ### 在SwooleServer中添加用戶自定義進程 ~~~ $server = new \Swoole\Server('127.0.0.1', 9501); /** * 自定義用戶進程實現廣播功能 * 循環接收管道消息,并發給服務器的所有連接 */ $process = new \Swoole\Process(function($process) use ($server) { // 用戶進程內應當進行while(true)或EventLoop循環,否則用戶進程會不停地退出重啟 while (true) { $msg = $process->read(); // 創建的子進程可以調用$server對象提供的各個方法和屬性 foreach($server->connections as $conn) { $server->send($conn, $msg); } } }); // 在swooleServer中新增進程時,子進程不需要start // 在Server啟動時會自動創建進程,并執行指定的子進程函數 $server->addProcess($process); $server->on('receive', function ($serv, $fd, $reactor_id, $data) use ($process) { //群發收到的消息 $process->write($data); }); $server->start(); ~~~ 可以參考easyswoole的編碼方式:http://www.easyswoole.com/Manual/3.x/Cn/_book/BaseUsage/process.html。 把復雜的業務邏輯寫進類里面,然后實例出來調用`getProcess()` ### 進程池 ~~~ // 設置10個工作進程 $workerNum = 10; $pool = new \Swoole\Process\Pool($workerNum); // 配置事件回調 $pool->on("WorkerStart", function ($pool, $workerId) { // 得到Process對象,可以使用Process對象的方法 $process = $pool->getProcess(); $process->exec("/bin/sh", ['-c', 'ls -l']); }); $pool->on("WorkerStop", function ($pool, $workerId) { echo "Worker#{$workerId} is stopped\n"; }); // 啟動工作進程 $pool->start(); ~~~ >[danger] 這邊測試下來,`onWorkerStart`事件一直重復觸發,按道理是只會在進程啟動的時候執行一次。原因未知。有可能是單核虛擬機的問題。 ### 進程信號異步監聽 [Linux信號列表](https://wiki.swoole.com/wiki/page/p-LinuxSignal.html) ~~~ // 監聽SIGTERM信號(停止) \Swoole\Process::signal(SIGTERM, function($signo) { echo "shutdown."; }); ~~~ ![](https://i.loli.net/2019/04/26/5cc2db7825118.png) 查到當前的進程pid為19093, 然后 `kill -9 19093`, 殺掉之后就輸出`shutdown.` ## 進程隔離與內存共享 進程和進程之間是隔離的。 * 不同的進程中PHP變量不是共享,即使是全局變量,在A進程內修改了它的值,在B進程內是無效的 * 如果需要在不同的Worker進程內共享數據,可以用`Redis`、`MySQL`、`文件`、`Swoole\Table`、`APCu`、`shmget`等工具實現 * 不同進程的文件句柄是隔離的,所以在A進程創建的Socket連接或打開的文件,在B進程內是無效,即使是將它的fd發送到B進程也是不可用的 ~~~ $server = new \Swoole\Http\Server('0.0.0.0', 9500); // 4個進程 $server->set([ 'worker_num' => 4]); $i = 1; $server->on('Request', function ($request, $response) { global $i; $response->end($i++); }); $server->start(); ~~~ 用兩個瀏覽器訪問上面的`HttpServer`,會發現輸出的$i都不一樣。如果是worker設置為1的話就一樣。因為`$i`變量雖然是全局變量(`global`),但由于進程隔離的原因。假設有`4`個工作進程,在`進程1`中進行`$i++`,實際上只有`進程1`中的`$i`變成`2`了,其他另外`3`個進程內`$i`變量的值還是`1`。 使用`Swoole\Table`來做到內存共享(其實更建議`redis`) ~~~ $server = new \Swoole\Http\Server('0.0.0.0', 9500); // 4個進程 $server->set([ 'worker_num' => 4]); // 參數指定表格的最大行數,必須為2的n次方,如果小于1024則默認成1024,即1024是最小值 // Table基于行鎖,所以單次set/get/del在多線程/多進程的環境下是安全的 // set/get/del等方法是原子操作,用戶代碼中不需要擔心數據加鎖和同步的問題 $table = new \Swoole\Table(8); // 字符串類型必須指定第三參數,如果是整型的話,注意溢出 $table->column('i',$table::TYPE_INT); $table->create(); $table->set('table',['i' => 1]); $server->on('Request', function ($request, $response) use($table) { $table->incr('table','i'); $response->end($table->get('table','i')); }); $server->start(); ~~~ 更多參考: https://wiki.swoole.com/wiki/page/p-table.html >[info] 進程在系統是非常昂貴的資源,創建進程消耗很大,要謹慎使用。如果要創建的子進程業務是要長期執行的,比如“監控文件文件變化”,可以使用子進程。其它短期任務,能用協程盡量用協程。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看