PHP 进程的实现与管理
應用場景
一些耗時任務:
所以我們就需要一個常駐內存的任務管理工具,為了保證實時性,一方面我們讓它一直執行任務(適當的睡眠,保證cpu不被100%占用),另一方面我們實現多進程保證并發的執行任務,當然除此之外也可按情況使用線程、協程實現。
運行模式
實現PHP進程前,需了解常見的php的運行模式:
而php進程則是使用CLI命令行模式運行的
基本實現
PHP中提供了一個擴展pcntl,可以利用操作系統的fork調用來實現多進程。fork調用后執行的代碼將是并行的,且只能在linux下運行。
$ppid = posix_getpid();// 獲取當前進程PID $pid = pcntl_fork(); //創建進程switch ($pid){// 創建進程錯誤case -1:throw new Exception('fork子進程失敗!');break;// 子進程workercase 0:$cpid = posix_getpid();cli_set_process_title("我是{$ppid}的子進程,我的進程id是{$cpid}.");sleep(30);exit; // 這里exit掉,避免worker繼續執行下面的代碼而造成一些問題break;// 主進程masterdefault:cli_set_process_title("我是父進程,我的進程id是{$ppid}.");pcntl_wait($status); // 掛起父進程,等待并返回子進程狀態,防止子進程成為僵尸進程break; }在命令行php xxx.php運行后,使用ps aux | grep 進程可以看到:
如果沒看到,可能是中文亂碼了,使用ps aux,查看
或者使用ps –ajft查看層次顯示
進程管理-防止進程成為僵尸進程
創建好了進程,那么怎么對子進程進行管理呢?使用信號,對子進程的管理,一般有兩種情況:
posix_kill():此函數并不能顧名思義,它通過向子進程發送一個信號來操作子進程,在需要要時可以選擇給子進程發送進程終止信號來終止子進程;
pcntl_waitpid():等待或返回fork的子進程狀態,如果指定的子進程在此函數調用時已經退出(俗稱僵尸進程),此函數將立刻返回,并釋放子進程的所有系統資源,此進程可以避免子進程變成僵尸進程,造成系統資源浪費;
孤兒進程:父進程掛了,子進程被pid=1的init進程接管(wait/waitpid),直到子進程自身生命周期結束被系統回收資源和父進程 采取相關的回收操作
僵尸進程:子進程exit退出,父進程沒有通過wait/waitpid獲取子進程狀態,子進程占用的進程號等描述資源符還存在,產生危害:例如進程號是有限的,無法釋放進程號導致未來可能無進程號可用
**父進程中使用:pcntl_wait或者pcntl_waitpid的目的就是防止worker成為僵尸進程
作用:使用pcntl_wait()后,在子進程死掉后,父進程也會被停止**
最后我們通過下圖(1-1)來簡單的總結和描述這個多進程實現的過程:
進程管理-進程間通信
隊列:如Redis,推薦
socket:推薦
管道:實現復雜,且管道(pipe),使用文件形式存在,存在硬盤IO性能瓶頸
信號:承載信息量少,不好管理
進程管理-切換為守護進程
使用&實現
php deadloop.php &
實際多進程的使用
一個耗時10S的任務,執行2次,總耗時20S,而開2個進程,只需10S,如下:
job.php:index.php(進程開啟腳本): echo '開始時間:'.date('H:i:s', time())."\n";$cmds = [['./job.php', 0, 50000],//執行腳本,并傳參['./job.php', 50000, 100000] ]; for ($i = 0; $i < 2; $i++){$ppid = posix_getpid();// 獲取當前進程PID$pid = pcntl_fork(); //創建進程switch ($pid){// 創建進程錯誤case -1:throw new Exception('fork子進程失敗!');break;// 子進程workercase 0:$cpid = posix_getpid();cli_set_process_title("我是{$ppid}的子進程,我的進程id是{$cpid}.");// 執行業務腳本pcntl_exec('/usr/local/php/bin/php', $cmds[$i]);exit; // 這里exit掉,避免worker繼續執行下面的代碼而造成一些問題break;} }// 等待子進程結束 while (pcntl_waitpid(0, $status) != -1) {$status = pcntl_wexitstatus($status);echo '子進程結束時間:'.date('H:i:s', time())."\n"; }
運行php index.php后:
實例達到理想效果。
總結
以上是生活随笔為你收集整理的PHP 进程的实现与管理的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【Jmeter】参数Parameters
- 下一篇: Redis入门(暂不更新)