什麼是進程
進程就是正在運行的程序的一個實例。
比如終端下運行一個PHP腳本,就是開啓了一個進程,就會有一個對應的進程ID,即PID。
查看官方文檔
創建一個SWOOLE
進程
在工作目錄創建 process.php
<?php
$process = new swoole_process(function(swoole_process $process){
echo 111;
}, true);
$pid = $process->start();
echo $pid . PHP_EOL;
// 當結束的時候,回收結束運行的子進程
swoole_process::wait();
注意:進程和進程之間是通過管道進行通信的。在實例化swoole_process
的時候,傳了第二個參數true
,這裏覺得輸出的內容不會打印到終端;如果設置爲false
,這裏可以打印到終端,這裏不做演示。
進程 process.php
啓動後,返回了進程ID,這裏我們輸出pid可以查看
[zhengzongqiang@localhost process]$ pwd
/opt/work/htdocs/swoole_mooc/demo/process
[zhengzongqiang@localhost process]$ php process.php
39388
創建一個HTTP
子進程
在process
進程開啓一個http
子進程,修改 process.php
文件
$process = new swoole_process(function(swoole_process $process){
// 這裏必須寫php的絕對安裝路徑. /
$process->exec("/opt/soft/php/bin/php", [__DIR__.'/../server/http.php']);
}, true);
$pid = $process->start();
echo $pid . PHP_EOL;
// 當結束的時候,回收結束運行的子進程
swoole_process::wait();
運行程序,會打印該swoole_process
進程的進程ID,即39658
[zhengzongqiang@localhost process]$ php process.php
39658
接下來我們在新的會話中通過查看端口驗證http
子進程是否開啓
[root@localhost zhengzongqiang]# netstat -anp | grep 8811
tcp 0 0 0.0.0.0:8811 0.0.0.0:* LISTEN 39658/php
可以看到,我們之前配置的http
服務端口已經被監聽,父進程ID爲39658
,即swoole_process
進程開啓了http
進程。
進程關係
進程開啓之後,可以通過命令跟進進程之間的關係。
// ps aux | grep process.php
[zhengzongqiang@localhost ~]$ ps aux | grep process.php
zhengzo+ 39657 0.0 0.8 161496 8412 pts/1 S+ 00:54 0:00 /opt/soft/php/bin/php process.php
zhengzo+ 39973 0.0 0.0 112720 980 pts/2 R+ 01:03 0:00 grep --color=auto process.php
可以查看到兩條進程,下邊一個代表運行本命令的進程,39657
即運行process.php
的程序的進程ID,即39658
的父進程,即39657
進程開啓了進程ID爲39658
的swool_process進程,即39657
就是php process.php這條命令的進程ID。
查看進程樹
通過以下命令可查看進程之間的關係
// pstree -p 39657
[zhengzongqiang@localhost ~]$ pstree -p 39657
php(39657)───php(39658)─┬─php(39659)───php(39661)
└─{php}(39660)
還可以通過以下命令查看進程的對應程序
// ps aft | grep http
[zhengzongqiang@localhost ~]$ ps aft | grep http
40193 pts/2 S+ 0:00 \_ grep --color=auto http
39658 pts/1 Sl+ 0:00 \_ /opt/soft/php/bin/php /opt/work/htdocs/swoole_mooc/demo/process/../server/http.php
39659 pts/1 S+ 0:00 \_ /opt/soft/php/bin/php /opt/work/htdocs/swoole_mooc/demo/process/../server/http.php
39661 pts/1 S+ 0:00 \_ /opt/soft/php/bin/php /opt/work/htdocs/swoole_mooc/demo/process/../server/http.php
我們可以看到,http
進程ID爲39659
,其父進程ID爲39658
進程,即swoole_process
進程,再父進程就是啓動swoole_process
進程的進程,即執行此文件的的命令的進程,即39657
進程。
39659
進程也有子進程,即worker進程。
可以理解爲39658
進程爲master進程,39659
進程爲manager進程。
SWOOLE 進程使用場景
有執行多個URL,需要獲取這鞋URL地址中的內容,然後把它記錄到相應的庫裏。
傳統PHP的做法是同步順序的執行這些URL,這個時候就會面另一個問題:
訪問每隔URL地址都會有耗時,積少成多,這樣會導致最後的響應時間太長,非常不友好。
這個問題可以通過引入swoole process
來解決,按需開啓N個子進程,每個子進程去執行相應的URL,這樣可以大大地縮短響應時間。
之前是一個主進程執行這些URl,引入swoole process
後,這個主進程可以開多個子進程,這樣每一個子進程去執行一個URl,時間就會大大縮短。
SWOOLE - DEMO
創建curl.php
// 傳統實現方式
$urls = [
'http://baidu.com',
'http://sina.com.cn',
'http://qq.com',
'http://baidu.com',
'http://sina.com.cn',
'http://qq.com'
];
foreach($urls as $url){
$content[] = file_get_contents($url);
}
這樣,如果每請求一個地址花費1s時間;那麼總共要花費6s。
通過swoole_process
實現
<?php
echo "process-start-time:".date('Y-m-d H:i:s').PHP_EOL;
$workers = [];
$urls = [
'http://baidu.com',
'http://sina.com.cn',
'http://qq.com',
'http://baidu.com',
'http://sina.com.cn',
'http://qq.com'
];
for($i = 0; $i < 6; $i++)
{
// 子進程
$process = new swoole_process(function(swoole_process $worker) use ($i, $urls){
$content = curlData($urls[$i]);
echo $content.PHP_EOL;
},true);
$pid = $process->start();
$workers[$pid] = $process;
}
foreach($workers as $worker){
echo $worker->read();
}
function curlData($url)
{
sleep(1);
return $url . 'success' . PHP_EOL ;
}
echo "process-end-time:" . date('Y-m-d H:i:s').PHP_EOL;
執行程序發現只用了1s
[zhengzongqiang@localhost process]$ php curl.php
process-start-time:2019-06-04 17:46:28
http://baidu.comsuccess
http://sina.com.cnsuccess
http://qq.comsuccess
http://baidu.comsuccess
http://sina.com.cnsuccess
http://qq.comsuccess
process-end-time:2019-06-04 17:46:29
注意:swoole
構造函數將內容輸出到管道,還有另一種方式
$worker->write($content.PHP_EOL);