Swoole進程模型

進程

什么是進程

進程Process是計算機中的程序關(guān)于某數(shù)據(jù)集合上的一次運行活動,是系統(tǒng)分配資源和調(diào)度的基本單位祭刚,是操作系統(tǒng)結(jié)構(gòu)的基礎(chǔ)预柒。在早期面向進程設(shè)計的計算機結(jié)構(gòu)中,進程是程序的基本執(zhí)行實體袁梗。在當代面向線程設(shè)計的計算機結(jié)構(gòu)中宜鸯,進程是線程的容器。簡單來說遮怜,程序是指令淋袖、數(shù)據(jù)以及其組織形式的描述,而進程則是程序的實體锯梁。

在操作系統(tǒng)中即碗,進程表示正在運行的程序焰情,例如在終端中使用PHP命令運行PHP腳本,此時就相當于創(chuàng)建了一個進程剥懒,這個進程會在系統(tǒng)中駐存内舟,申請屬于它自己的內(nèi)存空間和系統(tǒng)資源,并且運行相應的程序初橘。

$ php build.php
<?php
//獲取當前進程的PID
echo posix_getpid();
//修改所在進程的名稱
swoole_set_process_name("swoole process master");
//模擬持續(xù)運行100秒的程序
sleep(100);//持續(xù)運行100秒的目的是為了在進程中可以查看而不至于很快結(jié)束

運行程序

$ php build.php
71

查看進程

$ ps aux | grep 71
root         1  0.0  0.1  18188  1712 pts/0    Ss+  11:07   0:00 /bin/bash
root        71  0.0  3.0 340468 30788 pts/2    S+   13:41   0:00 swoole process master
root        76  0.0  0.0  11112   940 pts/1    S+   13:42   0:00 grep 71

對于一個進程來說验游,最核心的內(nèi)容可分為兩部分:一部分是它的內(nèi)存,這個內(nèi)存是在創(chuàng)建初始時從系統(tǒng)中分配的保檐,進程中所有創(chuàng)建的變量都會存儲在內(nèi)存環(huán)境中耕蝉。另一部分是上下文環(huán)境, 進程是運行在操作系統(tǒng)中的夜只,對于程序而言垒在,它的運行依賴于操作系統(tǒng)分配的資源、操作系統(tǒng)的狀態(tài)以及程序自身的狀態(tài)扔亥,這些就構(gòu)成了進程的上下文環(huán)境场躯。

父子進程

父子進程
  • 子進程會復制父進程的內(nèi)存空間和上下文環(huán)境
  • 子進程會復制父進程的IO句柄即fd描述符
  • 子進程的內(nèi)存空間與父進程的內(nèi)存空間是獨立,是互不影響的旅挤。
  • 修改子進程的內(nèi)存空間并不會修改父進程或其他子進程的內(nèi)存空間

例如:父進程通過fopen打開文件后得到一個IO句柄fd推盛,子進程復制父進程后同樣會得到這個fd。如果父進程和子進程同時對一個文件進行操作谦铃,會造成文件混亂耘成,因此需要加互斥鎖。

例如:父進程中的變量x=1驹闰,父進程派生子進程后瘪菌,子進程也會存在變量x=1,但是修改父進程中的變量x并不會影響子進程的變量x的值嘹朗。

多進程

PHP是單進程執(zhí)行的师妙,在處理高并發(fā)時主要依賴于Web服務器或PHP-FPM的多進程管理以及進程的復用,但在PHP實現(xiàn)多進程尤其是后臺PHP-CLI模式下處理大量數(shù)據(jù)或運行后臺Deamon守護進程時屹培,多進程的優(yōu)勢自然是最好的默穴。

PHP的多線程也曾被人提及,但進程內(nèi)多線程資源共享和分配問題難以解決褪秀,PHP有一個多線程過的擴展pthreads蓄诽,它要求PHP環(huán)境必須是線程安全的。

多進程簡單來說就是多個進程同時執(zhí)行多個任務媒吗,可以將耗時但又必須執(zhí)行的查詢分成多個子進程進行操作仑氛。

  • PHP多進程不支持PHP-FPM和CGI模式,只能通過PHP-CLI模式。
  • PHP多進程適用于定時任務執(zhí)行锯岖,互斥且耗時的任務介袜。

開發(fā)使用PHP多進程的場景也就是使用PHP-FPM,PHP-FPM作為PHP的多進程管理器出吹,當使用Nginx作為WebServer時遇伞,來自客戶端的請求會根據(jù)Nginx的路由配置,將以PHP為后綴的文件轉(zhuǎn)發(fā)給PHP-FPM捶牢。當多個用戶同時請求API時鸠珠,PHP-FPM會開啟多個PHP的處理進程進行處理。

檢查PHP是否支持多進程擴展

$ php -m | grep pcntl

多進程的優(yōu)勢

PHP相比C叫确、C++、Java少了多線程芍锦,PHP中只有多進程的方案竹勉,所以PHP中的全局變量和對象不是共享的,數(shù)據(jù)結(jié)構(gòu)也不能跨進程操作娄琉,另外Socket文件描述符也不能共享...

多線程看似比多進程強大的多次乓,多線程的缺陷也同樣明顯:

  • 數(shù)據(jù)同步時,要么犧牲性能到處加鎖孽水,要么使用地獄難度的無鎖并發(fā)編程票腰。
  • 當程序邏輯復雜后,鎖會越來越難以控制女气。一旦死鎖杏慰,程序基本上就完了。
  • 某個線程掛掉后所有的線程都會退出

相比較多線程炼鞠,多進程擁有的優(yōu)勢是

  • 配合進程間通信缘滥,基本可以實現(xiàn)任意數(shù)據(jù)共享。
  • 多進程不需要鎖
  • 多進程可以共享內(nèi)存的數(shù)據(jù)結(jié)構(gòu)實現(xiàn)一些多線程的功能

對于并發(fā)服務器核心是IO谒主,并非大規(guī)模密集運算朝扼,高并發(fā)的服務器單機能維持10W連接,每秒可以處理3~5W筆消息收發(fā)霎肯。

普通的Web應用都是IO密集型的程序擎颖,瓶頸在MySQL上,所以體現(xiàn)不出PHP的性能優(yōu)勢观游。但在密集計算方面比C/C++搂捧、Java等靜態(tài)編譯語言相差幾十倍甚至上百倍。

例如:使用多進程方式同時訪問Web地址

$ vim multi.php
<?php
echo "process begin: ".date("Y-m-d H:i:s").PHP_EOL;

//初始化地址數(shù)組
$urls = [
    "http://www.baidu.com",
    "http://www.360.com",
    "http://www.qq.com",
    "http://www.sina.com"
];
//初始化數(shù)組用于回收線程管道內(nèi)容
$workers = [];
//按照任務分配線程
for($i=0; $i<count($urls); $i++){
    $url = $urls[$i];
    //創(chuàng)建進程
    $process = new swoole_process(function(swoole_process $worker) use($url){
        //模擬執(zhí)行耗時任務
        file_get_contents($url);
        //sleep(1);//模擬耗時1秒
        echo $url.PHP_EOL;
    }, true);
    //開啟進程
    $pid = $process->start();
    $workers[$pid] = $process;
}
//打印管道內(nèi)容
foreach($workers as $worker){
    echo "pid : ".$worker->read();
}

echo "process end: ".date("Y-m-d H:i:s").PHP_EOL;

運行代碼

$ php multi.php
process begin: 2019-06-22 16:19:48
pid : http://www.baidu.com
pid : http://www.360.com
pid : http://www.qq.com
pid : http://www.sina.com
process end: 2019-06-22 16:19:49

內(nèi)存共享

進程之間是相互獨立的懂缕,那么如何實現(xiàn)進程之間的通信呢异旧? 這里可以使用共享內(nèi)存的方式來實現(xiàn)。

共享內(nèi)存ShareMemory是映射一段能被其他進程所訪問的內(nèi)存提佣,這段共享內(nèi)存由一個進程創(chuàng)建吮蛹,但多個進程都可以訪問荤崇。共享內(nèi)存是最快的IPC方式,是針對其他進程之間通信效率低下而專門設(shè)計的潮针,它往往與其它通信機制术荤,如信號量配置使用以實現(xiàn)進程之間的同步和通信。

共享內(nèi)存是操作系統(tǒng)中比較特殊的內(nèi)存每篷,它并不依賴于任何進程瓣戚, 也不屬于任何進程。通過調(diào)用系統(tǒng)函數(shù)創(chuàng)建共享內(nèi)存焦读,并指定它的索引子库,也就是它的IDshmid,通過索引任何進程都可以在共享內(nèi)存中申請內(nèi)存空間并存儲對應的值矗晃。

共享內(nèi)存
  • 共享內(nèi)存并不屬于任何一個進程
  • 在共享內(nèi)存中分配的內(nèi)存空間可以被任何進程訪問
  • 即使進程關(guān)閉仑嗅,共享內(nèi)存仍然可以繼續(xù)保存在操作系統(tǒng)中。

查看操作系統(tǒng)中共享內(nèi)存的分片

$ ipcs -m
------------ 共享內(nèi)存段 --------------
鍵        shmid      擁有者  權(quán)限     字節(jié)     連接數(shù)  狀態(tài)      
0x00000000 131072     jc         777        16384      1          目標       
0x00000000 327681     jc         600        67108864   2          目標       
0x00000000 262146     jc         777        8077312    2          目標     

Swoole沒有采用多線程模型而使用了多線程模型张症,在一定程度上減少了訪問數(shù)據(jù)時加鎖解鎖的開銷仓技,但同時也引入了新的需求 共享內(nèi)存。Swoole中為了更好的進行內(nèi)存管理俗他,減少頻繁分配釋放內(nèi)存空間造成的損耗和內(nèi)存碎片脖捻,Rango實際并實現(xiàn)了三種不同功能的內(nèi)存池分別時FixedPoolRingBuffer兆衅、MemoryGlobal地沮。

Swoole開發(fā)模式

對于傳統(tǒng)PHP的Web開發(fā)而言,最常用的是LNMP架構(gòu)羡亩。在LNMP架構(gòu)中诉濒,當請求進入時,WebServer會將請求轉(zhuǎn)交給PHP-FPM夕春,PHP-FPM是一個進程池架構(gòu)的FastCGI服務未荒,內(nèi)置了PHP解釋器。PHP-FPM負責解釋執(zhí)行PHP文件并生成響應及志,最終返回給WebServer展現(xiàn)至前端片排。由于PHP-FPM本身是同步阻塞進程模型,在請求結(jié)束后會釋放掉所有資源速侈,包括框架初始化創(chuàng)建的一些列對象率寡,從而導致PHP進程進入“空轉(zhuǎn)”消耗大量CPU資源,最終導致單機的吞吐能力有限倚搬。

另外冶共,在每次請求處理的過程都意味著一次PHP文件解析、環(huán)境設(shè)置等不必要的耗時操作,當PHP進程處理完后就會銷毀捅僵,無法在PHP程序中使用連接池等技術(shù)實現(xiàn)性能優(yōu)化家卖。

針對傳統(tǒng)架構(gòu)的問題,Swoole從PHP擴展下手庙楚,解決了上述問題上荡。相比較傳統(tǒng)的Web架構(gòu),Swoole進程模型最大的特點在于多線程Reactor模式處理網(wǎng)絡(luò)請求馒闷,使其能輕松應對大量連接酪捡。

除此之外,Swoole是全異步非阻塞纳账,因此占用資源少逛薇,程序執(zhí)行效率高。在Swoole中程序運行只解析加載一次PHP文件疏虫,避免每次請求的重復加載永罚。再者,Swoole進程常駐议薪,使得連接池和請求之間的信息傳遞的實現(xiàn)成為可能尤蛮。

使用Swoole開發(fā)時媳友,需要開發(fā)人員對多進程的運行模式有著清晰的認識斯议。另外,Swoole很容易造成內(nèi)存泄露醇锚。在處理全局變量哼御、靜態(tài)變量的時候要小心,這種不會被GC清理的變量會存在整個生命周期中焊唬。如果沒有正確的處理恋昼,很容易消耗完內(nèi)存。而在PHP-FPM下赶促,PHP代碼執(zhí)行完畢內(nèi)存就會被完全釋放掉液肌。

Swoole進程結(jié)構(gòu)

LNMP架構(gòu)中PHP是需要依賴Nginx這樣的Web服務器以及PHP-FPM這樣的多進程的PHP解析器。當一個請求到來時PHP-FPM會去創(chuàng)建一個新的進程去處理這個請求鸥滨,在這種情況下嗦哆,系統(tǒng)的開銷很大程序上都用在創(chuàng)建和銷毀進程上,導致了程序的響應效率并不是非常高婿滓。

Swoole的強大之處在于進程模型的設(shè)計老速,即解決了異步問題,又解決了并發(fā)問題凸主。

Swoole的進程可分為四種角色

  • Master進程
    保證Swoole機制運行橘券,同時利用它創(chuàng)建Master主線程(負責接收連接、定時器等)和Reactor線程(處理連接并將請求分發(fā)給各個Worker進程)。
  • Manager進程
    Worker進程和Task進程均由Manager進程派生旁舰,Manager管理進程負責結(jié)束時回收子進程锋华,避免僵尸進程的存在。
  • Worker進程
    用PHP回調(diào)函數(shù)處理由Reactor分發(fā)過來的請求數(shù)據(jù)鬓梅,并生成響應數(shù)據(jù)發(fā)送給Reactor供置,由Reactor發(fā)送給TCP客戶端。
  • Task進程
    接收由Worker進程分發(fā)給它的任務绽快,以多進程方式運行芥丧,處理好后將結(jié)果返回給它的Worker進程。
Swoole進程

Swoole中采用了和PHP-FPM完全不同的架構(gòu)坊罢,整個Swoole擴展可以分為三層:

Swoole進程模型

第1層:Master主進程

Master主進程

Master進程是Swoole的主進程续担,主要用于處理Swoole的核心事件驅(qū)動。Master主進程是一個多線程模型活孩,擁有多個獨立的Reactor線程物遇。

Master主進程包含Master線程、Reactor線程憾儒、心跳檢測線程询兴、UDP收包線程。每個Reactor子線程中都運行著一個epoll函數(shù)的實例起趾,Swoole對于事件的監(jiān)聽都會在Reactor線程中實現(xiàn)诗舰,比如來自客戶端的連接、本地通信使用的管道训裆、異步操作使用的文件以及文件描述符都會注冊在epoll函數(shù)中眶根。

Master主進程使用select/poll進行IO事件循環(huán),Master主進程中的文件描述符只有幾個边琉,Reactor線程使用epoll属百,因為Reactor線程中會監(jiān)聽大量連接的可讀事件,使用epoll可以支持大量的文件描述符变姨。

HTTP服務器為例族扰,Master主進程負責監(jiān)聽端口,然后接收新的連接定欧,并將這個連接分配給一個Reactor線程涯鲁,由這個Reactor線程監(jiān)聽此連接剩盒,一旦此連接可讀時,它會讀取數(shù)據(jù)并解析協(xié)議,然后將請求投遞到Worker工作進程中去執(zhí)行劈猪。

Master主進程內(nèi)的回調(diào)函數(shù)

  • onStart 服務器啟動時主進程的主線程回調(diào)此函數(shù)
  • onShutdown 服務器正常結(jié)束時發(fā)生

Master 線程

Swoole啟動后Master主線程會負責監(jiān)聽服務器的socket须鼎,如果有新的連接accept喜爷,Master主線程會評估每個Reactor線程的連接數(shù)量母市,并將此連接分配給連接最少的Reactor線程耍属。這樣做的好處是:

  • 每個Reactor線程持有的連接數(shù)非常均衡,沒有單個線程負載過高的問題巩检。
  • 解決了驚群問題厚骗,尤其是擁有多個listen socket時,節(jié)約了線程喚醒和切換的開銷兢哭。
  • 主線程接管了所有信號signal的處理领舰,使Reactor線程運行中可以不被信號打斷。

主線程Master在accept新的連接后迟螺,會將這個連接分配給一個固定的Reactor線程冲秽,并由這個線程負責監(jiān)聽此socket,在socket可讀時讀取數(shù)據(jù)矩父,并進行協(xié)議解析锉桑,最后將請求投遞到Worker進程。

Master主線程

Reactor線程

  • 負責維護客戶端TCP連接窍株、處理網(wǎng)絡(luò)IO民轴、處理協(xié)議、收發(fā)數(shù)據(jù)球订。
  • 完全是異步非阻塞的模式
  • 全部都是C代碼后裸,除了Start/Shutdown事件回調(diào)外,不執(zhí)行任何PHP代碼冒滩。
  • TCP客戶端發(fā)送來的數(shù)據(jù)緩沖微驶、拼接、拆分為完整的請求數(shù)據(jù)包旦部。
  • Reactor以多線程的方式運行

Swoole擁有多線程Reactor祈搜,所以可以充分利用多核较店,開啟CPU親和設(shè)置后士八,Reactor線程可以綁定單獨的核,節(jié)省CPU Cache開銷梁呈。

Reactor線程負責處理TCP連接婚度,是收發(fā)數(shù)據(jù)的線程。Swoole的Master主線程在accept新的連接后官卡,會將這個連接分配給一個固定的Reactor線程蝗茁,并由這個線程負責監(jiān)聽此socket。在socket可讀時讀取數(shù)據(jù)寻咒,并進行協(xié)議解析哮翘,將請求投遞到Worker工作進程。在socket可寫時毛秘,將數(shù)據(jù)發(fā)送給TCP客戶端饭寺。

Reactor線程負責維護客戶端TCP連接阻课、處理網(wǎng)絡(luò)IO、處理協(xié)議艰匙、收發(fā)數(shù)據(jù)限煞,它完全是異步非阻塞的模式。
Reactor線程是全異步非阻塞的员凝,即使Worker進程采用了同步模式署驻,依然不響應Reactor線程的性能。在Worker進程組很繁忙的狀態(tài)下健霹,Reactor線程完全不受影響旺上,依然可以收發(fā)處理數(shù)據(jù)。

由于TCP是流式的沒有邊界糖埋,所以處理起來很麻煩抚官。Reactor線程可以使用EOF或者包頭長度,自動緩存數(shù)據(jù)阶捆、組裝數(shù)據(jù)包凌节,等一個請求完全收到后,再次遞交給Worker洒试。

Reactor全部是C代碼倍奢,除了Start/Shutdown事件回調(diào)外,不執(zhí)行任何PHP代碼垒棋。它將TCP客戶端發(fā)來的數(shù)據(jù)緩沖卒煞、拼接、拆分成完整的一個請求數(shù)據(jù)包叼架。

綜上所述畔裕,Master主進程中包含兩個關(guān)鍵線程:Master主線程和Reactor線程,Master主線程用來處理accept()事件乖订,創(chuàng)建新的socket fd扮饶,當它接收到新連接后會將新的socket連接放到Reactor線程的事件監(jiān)聽循環(huán)中,Reactor線程負責接收從客戶端發(fā)送過來的數(shù)據(jù)乍构,并按協(xié)議解析后通過管道pipe傳遞給Worker工作進程進行處理甜无。Worker工作進程處理完畢后,會將結(jié)果通過管道pipe回傳給Reactor線程哥遮,Reactor線程再按照協(xié)議將結(jié)果通過socket發(fā)送給客戶端岂丘。可以看到Reactor線程負責數(shù)據(jù)的IO和傳輸眠饮,在Linux系統(tǒng)下這些IO事件都是通過epoll機制來處理的奥帘。

心跳包檢測線程HeartbeatCheck

Swoole配置了心跳檢測后心跳包線程會在固定事件內(nèi)對所有之前在線的連接發(fā)送檢測數(shù)據(jù)包。

UDP收包線程UdpRecv

接收并處理客戶端UDP數(shù)據(jù)包

第2層:Manager管理進程

Swoole運行中會創(chuàng)建一個單獨的管理進程仪召,所有的Worker進程和Task進程都是從管理進程fork創(chuàng)建出來的寨蹋。

Manager管理進程會監(jiān)聽所有子進程的退出事件牲距,當Worker進程發(fā)生致命錯誤或運行生命周期結(jié)束時,Manager管理進程會回收此進程并創(chuàng)建新的進程钥庇。

Manager管理進程還可以平滑地重啟所有工作進程Worker牍鞠,以實現(xiàn)程序代碼的重新加載。

Manager管理進程管理著Worker工作進程或Task任務進程评姨,Worker工作進程或Task任務進程都被Manager管理進程fork創(chuàng)建并管理著难述。

Manager進程負責創(chuàng)建和管理下層的Worker進程組和Task進程組,Manager進程中不會運行任何用戶層面的業(yè)務邏輯吐句,僅僅只做進程的管理和分配胁后。

Manager進程會fork創(chuàng)建出指定數(shù)量的Worker進程和Task進程。

Manager進程的工作職責

  • Worker工作進程和Task任務進程都是由Manager管理進程fork創(chuàng)建并管理的
  • 子進程結(jié)束運行時嗦枢,Manager管理進程負責回收子進程攀芯,以避免成為僵尸進程,并創(chuàng)建新的子進程文虏。
  • 服務器關(guān)閉時侣诺,Manager管理進程發(fā)送信號給所有子進程,并通知子進程關(guān)閉服務氧秘。
  • 服務器重啟時年鸳,Manager管理進程會逐個關(guān)閉或重啟子進程。

Manager進程內(nèi)的回調(diào)函數(shù)

  • onManagerStart 當管理進程啟動時調(diào)用
  • onManagerStop 當管理進程結(jié)束時調(diào)用
  • onWorkerError 當Worker進程或Task進程發(fā)生異常后會在Manager進程會回調(diào)此函數(shù)

第3層:工作進程

  • 工作進程主要用于處理客戶端請求
  • 工作進程接收由Reactor線程投遞的請求數(shù)據(jù)包丸相,并執(zhí)行PHP回調(diào)函數(shù)處理數(shù)據(jù)搔确。
  • 工作進程生成響應數(shù)據(jù)并發(fā)送給Reactor線程,由Reactor線程發(fā)送給TCP客戶端灭忠。
  • 工作進程可以是異步非阻塞模式也可以是同步阻塞模式膳算。
  • 工作進程以多進程的方式運行

與傳統(tǒng)的半同步半異步服務器不同是,Swoole的工作進程可以同步的也可以異步的弛作。這樣帶來了工作進程類似于PHP-FPM進程涕蜂,它接收由Reactor線程投遞的請求數(shù)據(jù)包,并執(zhí)行PHP回調(diào)函數(shù)處理數(shù)據(jù)缆蝉。工作線程生成響應數(shù)據(jù)并發(fā)送給Reactor線程宇葱,由Reactor線程發(fā)送給TCP客戶端瘦真。工作線程可以是異步模式刊头,也可以是同步模式。另外诸尽,工作線程以多進程的方式運行原杂。

Swoole想要實現(xiàn)最好的性能就必須創(chuàng)建出多個工作進程幫助處理任務,但是工作進程必須fork操作您机,而fork操作又是不安全的穿肄。如果沒有管理將會出現(xiàn)很多僵尸進程年局,進而影響服務器性能。同時工作進程被誤殺或由于程序原因會引起異常退出咸产,為了保證服務的穩(wěn)定性矢否,需要重新創(chuàng)建工作進程。

工作進程可分為兩類:Worker進程和Task進程

  • Worker進程是Swoole的主邏輯進程脑溢,用于處理來自客戶端的請求僵朗。

  • Task進程是Swoole提供的異步工作進程,用于處理耗時較長的同步任務屑彻。

Worker工作進程

Worker工作進程接收Reactor線程投遞過來的數(shù)據(jù)验庙,執(zhí)行PHP代碼,然后生成數(shù)據(jù)并交給Reactor線程社牲,由Reactor線程通過TCP將數(shù)據(jù)返回給客戶端粪薛。如果是UDP,Worker工作進程會直接將數(shù)據(jù)發(fā)送給客戶端搏恤。

Worker進程中執(zhí)行的PHP代碼违寿,它等同于PHP-FPMPHP-FPM在處理異步操作時是很無力的熟空,但Swoole提供的Task進程可以很好的解決這個問題陨界。Worker進程可以將一些異步任務投遞給Task進程,然后直接返回痛阻,處理其他由Reactor線程投遞過來的事件菌瘪。

Worker進程內(nèi)的回調(diào)函數(shù)

  • onWorkerStart 當Worker工作進程或Task任務進程啟動時觸發(fā)
  • onWorkerStop 當Worker進程終止時觸發(fā)
  • onConnect 當有新的連接進入時觸發(fā)
  • onClose 當TCP客戶端連接關(guān)閉后觸發(fā)
  • onReceive 當接收到數(shù)據(jù)時觸發(fā)
  • onPacket 當接收到UDP數(shù)據(jù)包是時觸發(fā)
  • onFinish 當Worker工作進程投遞的任務在task_worker中完成時,Task進程會通過finish()方法將任務處理的結(jié)果發(fā)送給Worker進程阱当。
  • onWorkerExit 當開啟reload_async特性后有效俏扩,即異步重啟特性。
  • onPipeMessage 當工作進程收到由sendMessage發(fā)送的管道消息時觸發(fā)

Task任務進程

  • 異步工作進程
  • 接收由Worker工作進程通過swoole_server->taskswoole_server->taskwait方法投遞的任務弊添。
  • 處理任務录淡,并將結(jié)果數(shù)據(jù)返回給Worker工作進程swoole_server->finish
  • 同步阻塞模式
  • 以多進程的方式運行

Swoolen除了Reactor線程油坝,Task任務工作進程是以異步的方式處理其它任務的進程嫉戚,使用方式類似于Gearman。它接收由Worker進程通過swoole_server->task/taskwait方法投遞的任務澈圈,然后處理任務彬檀,并將結(jié)果數(shù)據(jù)使用swoole_server->finish返回給Worker進程。Task以多進程的方式進行運行瞬女。

簡單來說窍帝,可以將Reactor理解為Nginx,將Worker理解為PHP-FPM诽偷。Reactor線程異步并行地處理網(wǎng)絡(luò)請求坤学,然后再轉(zhuǎn)發(fā)給Worker工作進程中去處理(在回調(diào)函數(shù)中處理)疯坤。Reactor和Worker之間通過UnixSocket進行通信。

Swoole除了Reactor線程深浮,Worker工作進程還提供了Task進程池压怠。目的是為了解決業(yè)務代碼中,有些邏輯部分不需要馬上執(zhí)行飞苇。利用Task進程池刑峡,可以方便的投遞一個異步任務區(qū)執(zhí)行。

Task進程以完全同步阻塞的方式運行玄柠,一個Task進程在執(zhí)行任務期間是不接受從Worker進程投遞的任務的突梦,當Task進程執(zhí)行完任務后,會異步的通知Worker進程并告訴它任務已經(jīng)完成羽利。

Task進程內(nèi)的回調(diào)函數(shù)

  • onTask 在Task線程內(nèi)被調(diào)用宫患,Worker進程可使用swoole_server_task函數(shù)向Task進程投遞新的任務。
  • onWorkerStart 在Worker或Task進程啟動時觸發(fā)
  • onPipeMessage 當工作進程收到由sendMessage發(fā)送的管道消息時觸發(fā)
Swoole的進程

Swoole進程協(xié)作

  1. 當客戶端主動連入服務器的時候这弧,客戶端實際上是與Master主進程中的某個Reactor線程發(fā)生了連接娃闲。
  2. 當TCP三次握手成功后,由這個Reactor線程將連接成功的消息告知Manager管理進程匾浪,再由Manager管理進程轉(zhuǎn)交給Worker工作進程皇帮,最終在Worker工作進程中觸發(fā)onConnect事件對應的方法。
  3. 當客戶端向服務器發(fā)送一個數(shù)據(jù)包的時候蛋辈,首先接收到數(shù)據(jù)包的是Reactor線程属拾,同時Reactor線程會完成組包,再將組裝好的包交給Manager管理進程冷溶,由Manager管理進程轉(zhuǎn)交給Worker工作進程渐白,此時Worker工作進程觸發(fā)onReceive事件。
  4. 如果Worker工作進程中做了處理操作后再使用Send方法將數(shù)據(jù)發(fā)回給客戶端時逞频,數(shù)據(jù)會沿著這個路徑逆流而上纯衍。
  5. Task任務進程用來處理一些占用時間較長的業(yè)務,主要處理Worker工作進程中占用時間較長的任務苗胀。

形象來說

  • Master主進程 = 業(yè)務窗口
  • Reactor線程 = 前臺接待員
  • Manager管理進程 = 項目經(jīng)理
  • Worker工作進程 = 工人

當在業(yè)務窗口辦理業(yè)務時襟诸,如果用戶很多,后邊的用戶需要排隊等待服務基协,Reactor負責與客戶直接溝通歌亲,對客戶的請求進行初步的整理(傳輸層級別的整理,組包)堡掏,然后Manager負責將業(yè)務分配給合適的Worker应结,如空閑的Worker,最終Worker負責實現(xiàn)具體的業(yè)務泉唁。

Swoole進程關(guān)系

Reactor和Worker與Task的關(guān)系鹅龄,簡單理解可認為:Reactor = Nginx、Worker = PHP-FPM

Reactor線程異步并行地處理網(wǎng)絡(luò)請求亭畜,然后再轉(zhuǎn)發(fā)給Worker工作進程中去處理扮休。

Reactor線程和Worker工作進程之間通過socket進行通信。

在PHP-FPM的應用中拴鸵,經(jīng)常會將一個任務異步投遞到Redis等隊列中玷坠,并在后臺啟動一些PHP進程異步地處理這些任務。

Swoole提供的Worker工作進程是一套更加完整的方案劲藐,它將任務投遞八堡、隊列、PHP任務進程管理融為一體聘芜。通過底層的API實現(xiàn)異步任務的處理兄渺。另外,Task任務進程可以在任務執(zhí)行完畢后汰现,再返回一個結(jié)果反饋到Worker工作進程挂谍。

Swoole的Reactor、Worker瞎饲、Task之間可以緊密的結(jié)合起來口叙,提供更加高級的使用方式。

假設(shè)Server是一個工廠

  • Reactor:銷售嗅战,接收客戶訂單妄田。
  • Worker:工人,當銷售接單后驮捍,Worker去工作生產(chǎn)出客戶需要的東西形庭。
  • Task:行政人員,幫助Worker干些雜事兒厌漂,讓Worker專心工作萨醒。

底層會為Worker工作進程、Task任務進程分配一個唯一的ID苇倡,不同的Worker和Task任務進程之間可以通過sendMessage接口進行通信富纸。

Swoole執(zhí)行流程

Swoole執(zhí)行流程
  1. 當客戶端請求進入Master主進程后會被Master主線程接收到
  2. 將讀寫操作的監(jiān)聽注冊到對應的Reactor線程中,并通知Worker工作進程處理onConnect旨椒,也就是接收到連接的回調(diào)晓褪。
  3. 客戶端的數(shù)據(jù)會通知對應的Reactor線程并發(fā)送給Worker工作進程進行處理。
  4. 如果Worker工作進程投遞任務综慎,將數(shù)據(jù)通過管道發(fā)送給Task任務進程涣仿,Task任務進程處理完后會發(fā)送給Worker工作進程。
  5. Worker工作進程會通知Reactor線程發(fā)送數(shù)據(jù)給客戶端。
  6. 當Worker工作進程出現(xiàn)異常時關(guān)閉好港,Manager管理進程會重新創(chuàng)建一個Worker工作進程愉镰,保證Worker工作進程的數(shù)量是固定的。
Swoole執(zhí)行流程
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末钧汹,一起剝皮案震驚了整個濱河市丈探,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌拔莱,老刑警劉巖碗降,帶你破解...
    沈念sama閱讀 211,290評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異塘秦,居然都是意外死亡讼渊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,107評論 2 385
  • 文/潘曉璐 我一進店門尊剔,熙熙樓的掌柜王于貴愁眉苦臉地迎上來爪幻,“玉大人,你說我怎么就攤上這事赋兵”恃剩” “怎么了?”我有些...
    開封第一講書人閱讀 156,872評論 0 347
  • 文/不壞的土叔 我叫張陵霹期,是天一觀的道長叶组。 經(jīng)常有香客問我,道長历造,這世上最難降的妖魔是什么甩十? 我笑而不...
    開封第一講書人閱讀 56,415評論 1 283
  • 正文 為了忘掉前任,我火速辦了婚禮吭产,結(jié)果婚禮上侣监,老公的妹妹穿的比我還像新娘。我一直安慰自己臣淤,他們只是感情好橄霉,可當我...
    茶點故事閱讀 65,453評論 6 385
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著邑蒋,像睡著了一般姓蜂。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上医吊,一...
    開封第一講書人閱讀 49,784評論 1 290
  • 那天钱慢,我揣著相機與錄音,去河邊找鬼卿堂。 笑死束莫,一個胖子當著我的面吹牛懒棉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播览绿,決...
    沈念sama閱讀 38,927評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼策严,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了挟裂?” 一聲冷哼從身側(cè)響起享钞,我...
    開封第一講書人閱讀 37,691評論 0 266
  • 序言:老撾萬榮一對情侶失蹤揍诽,失蹤者是張志新(化名)和其女友劉穎诀蓉,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體暑脆,經(jīng)...
    沈念sama閱讀 44,137評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡渠啤,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,472評論 2 326
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了添吗。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片沥曹。...
    茶點故事閱讀 38,622評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖碟联,靈堂內(nèi)的尸體忽然破棺而出妓美,到底是詐尸還是另有隱情,我是刑警寧澤鲤孵,帶...
    沈念sama閱讀 34,289評論 4 329
  • 正文 年R本政府宣布壶栋,位于F島的核電站,受9級特大地震影響普监,放射性物質(zhì)發(fā)生泄漏贵试。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,887評論 3 312
  • 文/蒙蒙 一凯正、第九天 我趴在偏房一處隱蔽的房頂上張望毙玻。 院中可真熱鬧,春花似錦廊散、人聲如沸桑滩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,741評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽运准。三九已至,卻和暖如春擂找,著一層夾襖步出監(jiān)牢的瞬間戳吝,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,977評論 1 265
  • 我被黑心中介騙來泰國打工贯涎, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留听哭,地道東北人。 一個月前我還...
    沈念sama閱讀 46,316評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像陆盘,于是被迫代替她去往敵國和親普筹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,490評論 2 348

推薦閱讀更多精彩內(nèi)容

  • 前文再續(xù)隘马,就書接上一回太防,隨著與Server、TCP酸员、Protocol的邂逅蜒车,Swoole終于迎來了自己的故事,今天...
    蝸牛淋雨閱讀 1,723評論 1 14
  • swoole的強大之處就在與其進程模型的設(shè)計幔嗦,既解決了異步問題酿愧,又解決了并行。 主線程MainReactor sw...
    Yagami_閱讀 614評論 0 0
  • 前言 前文再續(xù)邀泉,就書接上一回嬉挡,隨著與Server、TCP汇恤、Protocol的邂逅庞钢,Swoole終于迎來了自己的故事...
    零一間閱讀 5,254評論 0 17
  • 進程基本概念 狹義定義:進程是正在運行的程序的實例(an instance of a computer progr...
    zshanjun閱讀 763評論 1 0
  • 天外飄雪,室內(nèi)如春因谎,康寶甜睡状囱,我在畫荷材失,盼夏快至镰矿,帶兒外耍哭懈。
    榛木月月閱讀 162評論 3 1