十年網(wǎng)站開發(fā)經(jīng)驗 + 多家企業(yè)客戶 + 靠譜的建站團隊
量身定制 + 運營維護+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
小編給大家分享一下swoole之進程模型的示例分析,相信大部分人都還不怎么了解,因此分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后大有收獲,下面讓我們一起去了解一下吧!
創(chuàng)新互聯(lián)服務(wù)項目包括牡丹網(wǎng)站建設(shè)、牡丹網(wǎng)站制作、牡丹網(wǎng)頁制作以及牡丹網(wǎng)絡(luò)營銷策劃等。多年來,我們專注于互聯(lián)網(wǎng)行業(yè),利用自身積累的技術(shù)優(yōu)勢、行業(yè)經(jīng)驗、深度合作伙伴關(guān)系等,向廣大中小型企業(yè)、政府機構(gòu)等提供互聯(lián)網(wǎng)行業(yè)的解決方案,牡丹網(wǎng)站推廣取得了明顯的社會效益與經(jīng)濟效益。目前,我們服務(wù)的客戶以成都為中心已經(jīng)輻射到牡丹省份的部分城市,未來相信會繼續(xù)擴大服務(wù)區(qū)域并繼續(xù)獲得客戶的支持與信任!
初識server一文的時候我們說過,swoole是事件驅(qū)動的。在使用swoole的過程中,我們也體會到,swoole的使用非常簡單,僅僅注冊相應(yīng)的回調(diào)處理我們的業(yè)務(wù)邏輯即可。
但是,在繼續(xù)學(xué)習(xí)swoole之前,我們有必要再看一看swoole的運行流程和進程模型。
推薦(免費):swoole
前面兩篇文章我們已經(jīng)對server和task做了簡單的介紹,后面再對server的創(chuàng)建以及腳本的執(zhí)行,如無特殊說明均在CLI下執(zhí)行,我就不啰嗦了。
現(xiàn)在,我們創(chuàng)建一個簡單的server來分析一下,文件命名為server-process.php
$serv = new swoole_server('127.0.0.1', 9501); $serv->set([ 'worker_num' => 2, 'task_worker_num' => 1, ]); $serv->on('Connect', function ($serv, $fd) { }); $serv->on('Receive', function ($serv, $fd, $fromId, $data) { }); $serv->on('Close', function ($serv, $fd) { }); $serv->on('Task', function ($serv, $taskId, $fromId, $data) { }); $serv->on('Finish', function ($serv, $taskId, $data) { }); $serv->start();
注意這里我們選擇了兩個worker進程個一個task進程,那是不是就意味著創(chuàng)建這個server就是開啟了3個進程呢?我們來看下
新開一個終端,我們用ps命令看下結(jié)果
$ ps aux | grep server-process root 21843 xxx... php server-process.php root 21844 xxx... php server-process.php root 21846 xxx... php server-process.php root 21847 xxx... php server-process.php root 21848 xxx... php server-process.php root 21854 xxx... grep --color=auto server-process
為了方便閱讀,ps的結(jié)果中部分不重要數(shù)據(jù)已經(jīng)被稍加處理了。
排除最后一個結(jié)果(最后一個是我們運行的ps命令)我們發(fā)現(xiàn),竟然有多達5個相似的進程在運行,按照我們理解,不應(yīng)該是3個嗎,怎么多了兩個呢?
還記得我們在進程/線程一文中說過的多進程的實現(xiàn)嗎?我們說到多進程的實現(xiàn)一般會被設(shè)計Master-Worker模式,常見的nginx默認的多進程模式也正是如此,當(dāng)然swoole默認的也是多進程模型。
相比Master-Worker模式,swoole的進程模型可以用Master-Manager-Worker來形容。即在Master-Worker的基礎(chǔ)上又增加了一層Manager進程。這也就解答了我們開頭拋出的問題為什么是5個進程而不是3個進程了。(1個Master進程+1個Manager進程+2個Worker進程+1個Task進程)
正所謂“存在即合理”,我們來看一下Master\Manager\Worker三種進程各自存在的原因。
Master進程是一個多線程程序。注解:按照我們之前的理解,多個線程是運行在單一進程的上下文中的,其實對于單一進程中的每一個線程,都有它自己的上下文,但是由于共同存在于同一進程,所以它們也共享這個進程,包括它的代碼、數(shù)據(jù)等等。
再回來繼續(xù)說Master進程,Master進程就是我們的主進程,掌管生殺大權(quán),它掛了,那底下的都得玩完。Master進程,包括主線程,多個Reactor線程等。
每一個線程都有自己的用途,比如主線程用于Accept、信號處理等操作,而Reactor線程是處理tcp連接,處理網(wǎng)絡(luò)IO,收發(fā)數(shù)據(jù)的線程。
說明兩點:
主線程的Accept操作,socket服務(wù)端經(jīng)常用accept阻塞,上一節(jié)介紹socket編程的時候有一張配圖,可以看看
信號處理,信號就相當(dāng)于一條消息,比如我們經(jīng)常操作的Ctrl+C其實就是給Master進程的主線程發(fā)送一個SIGINT的信號,意思就是你可以終止啦,信號有很多種,后面還有介紹
通常,主線程處理完新的連接后,會將這個連接分配給固定的Reactor線程,并且這個Reactor線程會一直負責(zé)監(jiān)聽此socket(上文中后面對socket更新為socket即套接字,是用來與另一個進程進行跨網(wǎng)絡(luò)通信的文件,文件可讀可寫),換句話就是說當(dāng)此socket可讀時,會讀取數(shù)據(jù),并將該請求分配給worker進程,這也就解釋了我們在swoole初識講解worker進程內(nèi)的回調(diào)onReceive的第三個參數(shù)$fromId的含義;當(dāng)此socket可寫時,會把數(shù)據(jù)發(fā)送給tcp客戶端。
用一張圖清晰的梳理下
那swoole為啥不能像Nginx一樣,是Master-Worker進程結(jié)構(gòu)的呢?Manager進程是干啥的?
這個我正準(zhǔn)備說。
我們知道,在Master-Worker模型中,Master只有一個,Worker是由父進程Master進程復(fù)制出來的,且Worker進程可以有多個。
注解:在linux中,父進程可以通過調(diào)用fork函數(shù)創(chuàng)建一個新的子進程,子進程是父進程的一個副本,幾乎但不完全相同,二者的最大區(qū)別就是都擁有自己獨立的進程ID,即PID。
對于多線程的Master進程而言,想要多Worker進程就必須fork操作,但是fork操作是不安全的,所以,在swoole中,有一個專職的Manager進程,Manager進程就專門負責(zé)worker/task進程的fork操作和管理。換句話也就是說,對于worker進程的創(chuàng)建、回收等操作全權(quán)有“保姆”Manager進程進行管理。
通常,worker進程被誤殺或者由于程序的原因會異常退出,Manager進程為了保證服務(wù)的穩(wěn)定性,會重新拉起新的worker進程,意思就是Worker進程你發(fā)生意外“死”了,沒關(guān)系,我自身不“死”,就可以fork千千萬萬個你。
當(dāng)然,Master進程和Manager進程我們是不怎么關(guān)心的,從前面兩篇文章我們了解到,真正實現(xiàn)業(yè)務(wù)邏輯,是在worker/task進程內(nèi)完成的。
再來一張圖梳理下Manager進程和Worker/Task進程的關(guān)系。
再回到我們開篇拋出的的5個進程的問題,ps的結(jié)果簡直一模一樣,有沒有辦法能區(qū)分這5個進程哪個是哪個呢?
有同學(xué)要說啦,既然各個進程之間存在父子關(guān)系,那我們就可以通過linux的pstree命令查看結(jié)果。
$ pstree | grep server-process | | \-+= 02548 manks php server-process.php | | \-+- 02549 manks php server-process.php | | |--- 02550 manks php server-process.php | | |--- 02551 manks php server-process.php | | \--- 02552 manks php server-process.php | \--- 02572 manks grep server-process
注:centos下命令可修改為 pstree -ap | grep server-process
從結(jié)果中我們可以看出,進程id等于02548的進程就是Master進程,因為從結(jié)構(gòu)上看就它是“父”嘛,02549是Manager進程,Worker進程和Task進程就是02550、02551和02552了(每個人的電腦上顯示的進程id可能不同,但順序是一致的,依照此模型分析即可)。
我們看到pstree命令也只能得到大致結(jié)果,而且在事先不知道的情況下,根本無法區(qū)分Worker進程和Task進程。
在swoole中,我們可以在各個進程啟動和關(guān)閉的回調(diào)中去解決上面這個問題。各個進程的啟動和關(guān)閉?那豈不是又要記住主進程、Manager進程、Worker進程,二三得六,6個回調(diào)函數(shù)?
是的,不過這6個是最簡單也是最好記的,你實際需要了解的可能還要更多。
Master進程: 啟動:onStart 關(guān)閉:onShutdown Manager進程: 啟動:onManagerStart 關(guān)閉:onManagerStop Worker進程: 啟動:onWorkerStart 關(guān)閉:onWorkerStop
提醒:task_worker也會觸發(fā)onWorkerStart回調(diào)。
是不是很好記?那我們就在server-process.php中通過上面這幾種回調(diào)來實現(xiàn)對各個進程名的修改。
$serv->on("start", function ($serv){ swoole_set_process_name('server-process: master'); }); // 以下回調(diào)發(fā)生在Manager進程 $serv->on('ManagerStart', function ($serv){ swoole_set_process_name('server-process: manager'); }); $serv->on('WorkerStart', function ($serv, $workerId){ if($workerId >= $serv->setting['worker_num']) { swoole_set_process_name("server-process: task"); } else { swoole_set_process_name("server-process: worker"); } });
注意:因mac下不支持swoole_set_process_name函數(shù),即不能修改進程名,我們換臺centos運行下看看結(jié)果(實際上你的服務(wù)器也不可能是mac)
# ps aux | grep server-process root 27546 xxx... server-process: master root 27547 xxx... server-process: manager root 27549 xxx... server-process: task worker root 27550 xxx... server-process: worker root 27551 xxx... server-process: worker root 27570 xxx... grep --color=auto simple
運行結(jié)果誰是誰一目了然,簡直了!
有同學(xué)傻眼了,說在workerStart回調(diào)中寫的看不明白,worker進程和task進程怎么區(qū)分的?
我來解釋一下:在onWorkerStart回調(diào)中,$workerId表示的是一個值,這個值的范圍是0~worker_num,worker_num是我們的對worker進程的配置,其中0~worker_num表示worker進程的標(biāo)識,包括0但不包括worker_num;worker_num~worker_num+task_worker_num是task進程的標(biāo)識,包括worker_num不包括worker_num+task_worker_num。
按照高中學(xué)的區(qū)間的知識可能更好理解,以我們案例的配置,workerId的值的范圍就是[0,2],[0,2)表示worker進程,[2,3)就表示task_worker進程。
swoole的進程模型很重要,本篇掌握不好,后面的理解可能就會有些問題。
我們在onWorkerStart的回調(diào)中,用了serv?>setting去獲取配置的server信息,在swoole中預(yù)留了一些swooleserver的屬性,我們可以在回調(diào)函數(shù)中訪問。比如說我們可以用serv?>setting去獲取配置的server信息,在swoole中預(yù)留了一些swooleserver的屬性,我們可以在回調(diào)函數(shù)中訪問。比如說我們可以用serv->connections屬性獲取當(dāng)前server的所有的連接,再比如我們可以通過$serv->master_pid屬性獲取當(dāng)前server的主進程id等等。
以上是“swoole之進程模型的示例分析”這篇文章的所有內(nèi)容,感謝各位的閱讀!相信大家都有了一定的了解,希望分享的內(nèi)容對大家有所幫助,如果還想學(xué)習(xí)更多知識,歡迎關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道!