MixPHP V2.1 為何從 Reactor+Manager+Worker 多進(jìn)程改為單線程協(xié)程

Mix V2.1 之前的版本一直采用與現(xiàn)在主流的 Swoole 框架一樣基于多進(jìn)程 Swoole\Server 開(kāi)發(fā),V2.1 開(kāi)始 Mix 全部基于 Swoole 的 Coroutine/Server 開(kāi)發(fā) (單線程協(xié)程),讓 Server 也可使用完全同步的編程方式,底層自動(dòng)實(shí)現(xiàn)異步IO。

Reactor+Manager+Worker 多進(jìn)程優(yōu)缺點(diǎn)

Master+Worker 的進(jìn)程模型是一種應(yīng)用廣泛的傳統(tǒng)模型,像 Nginx、PHP-FPM 均采用這種模型,但 Swoole 的模型中多了一個(gè) Manager 進(jìn)程。

Swoole 進(jìn)程模型

優(yōu)點(diǎn):

  • 可自行重啟:
    Reactor+Manager+Worker 進(jìn)程架構(gòu)最大的優(yōu)點(diǎn)就是,當(dāng) Worker 出現(xiàn)任何異常,無(wú)需借助第三方 (如:supervisor、pm2) 即可由程序本身的 Manager 進(jìn)程重啟一個(gè) Worker 進(jìn)程。
  • 可利用多CPU:
    由于是多進(jìn)程模型,Worker 進(jìn)程執(zhí)行在多個(gè)CPU中,因此可利用到多核。
  • 阻塞影響?。?br> 因?yàn)?Reactor 多線程負(fù)責(zé)連接處理,而多個(gè) Worker 進(jìn)程負(fù)責(zé)執(zhí)行 PHP 代碼,因此單個(gè) Worker 的阻塞IO并不會(huì)影響其他請(qǐng)求 (協(xié)程模式,會(huì)影響到分配到該進(jìn)程但沒(méi)有執(zhí)行完成的請(qǐng)求)

缺點(diǎn):

  • 編碼復(fù)雜、不夠靈活:
    Swoole\Server 在啟動(dòng)前與啟動(dòng)后 class 的屬性操作的作用域,對(duì)不熟悉的用戶非常不友好,容易掉坑,難以理解。處理一些全局業(yè)務(wù)時(shí)需要跨進(jìn)程處理,帶來(lái)并發(fā)安全鎖的問(wèn)題,且無(wú)法同時(shí)啟動(dòng)多個(gè) Server 或者自由的在代碼中隨意啟動(dòng)停止 Server。
  • 平滑shutdown困難:
    由于程序執(zhí)行在很多個(gè) Worker 進(jìn)程中,如果存在耗時(shí)任務(wù),多進(jìn)程模型很難精細(xì)的控制每個(gè)子進(jìn)程執(zhí)行完管道的全部請(qǐng)求,然后平滑有序的退出所有進(jìn)程,Swoole\Server 雖然提供了 異步安全重啟特性 但是大部分框架是沒(méi)有處理 onWorkerExit 的,用戶也很難在框架基礎(chǔ)上擴(kuò)展。

單線程協(xié)程優(yōu)缺點(diǎn)

單線程模型在新創(chuàng)軟件領(lǐng)域非常流行,像 Redis、Node.js 都是單線程模型,而優(yōu)缺點(diǎn)剛好與 Reactor+Manager+Worker 相反,但是 Mix 針對(duì)這些缺點(diǎn)提供了解決方案。

缺點(diǎn):

  • 無(wú)法自行重啟:
    Mix V2.1 這個(gè)問(wèn)題普遍存在于所有單進(jìn)程程序中,包括 Golang、Node.js 開(kāi)發(fā)的程序,在出現(xiàn)致命異常時(shí)都會(huì)導(dǎo)致進(jìn)程退出,由于是單進(jìn)程所以無(wú)法自行重啟,都需要借助第三方 (如:supervisor、pm2)
  • 無(wú)法利用多CPU:
    由于是單進(jìn)程模型,執(zhí)行在一個(gè)CPU中,因此和 Node.js 一樣無(wú)法利用多核 (使用 docker 部署則無(wú)此問(wèn)題)。
  • 阻塞影響大:
    單進(jìn)程模型由于 Server 與業(yè)務(wù)邏輯一同執(zhí)行在單個(gè)進(jìn)程內(nèi),因此當(dāng)遇到阻塞IO時(shí),所有請(qǐng)求處理都會(huì)一起阻塞,導(dǎo)致響應(yīng)時(shí)間變長(zhǎng),長(zhǎng)時(shí)間的阻塞還會(huì)導(dǎo)致服務(wù)無(wú)法接收新的請(qǐng)求,Swoole 雖然 Hook 了大量的阻塞IO能支持協(xié)程,但還是有許多擴(kuò)展是無(wú)法支持的,因此該問(wèn)題最為突出。

優(yōu)點(diǎn):

  • 編碼簡(jiǎn)單、靈活:
    由于是單進(jìn)程單線程模型,加上 Server 全部基于 Swoole 的 Coroutine/Server 開(kāi)發(fā),完全同步的編程方式,因此代碼非常簡(jiǎn)單易懂。也沒(méi)有了多進(jìn)程帶來(lái)的:跨進(jìn)程對(duì)象屬性分歧問(wèn)題,并發(fā)安全鎖問(wèn)題,Server 也可隨意啟動(dòng) N 個(gè)、隨意停止。
  • 平滑shutdown簡(jiǎn)單:
    單線程模型,處理信號(hào)只需處理一個(gè)進(jìn)程,退出也只需處理一個(gè)進(jìn)程,由于是同步編程方式,退出的處理邏輯也非常簡(jiǎn)單易懂。

對(duì)缺點(diǎn)的解決方案

通過(guò)上面分析可以得出結(jié)論:?jiǎn)尉€程更加簡(jiǎn)單靈活,但是最大的缺點(diǎn)就是阻塞問(wèn)題,和多CPU利用問(wèn)題,Mix V2.1 如何解決這些問(wèn)題:

  • 多CPU利用:
    與 Node.js 解決該問(wèn)題的方法一樣,通過(guò)多開(kāi)進(jìn)程來(lái)解決多CPU利用問(wèn)題,由于同一個(gè)端口只能被一個(gè)程序綁定,因此多開(kāi)只能綁定不同端口,勢(shì)必增加了反向代理的復(fù)雜度,但在 Linux v3.10 或更高版本內(nèi)核中加入了端口復(fù)用功能,Mix 內(nèi)置的 Server 只需啟動(dòng)時(shí)增加 -r 參數(shù)即可在 Linux 中多開(kāi)端口復(fù)用,達(dá)到與 Node.js 類似的解決多CPU利用的效果,查看范例。

  • 阻塞:
    單進(jìn)程單線程模型中要徹底解決 PHP 歷史遺留的阻塞IO問(wèn)題,只能通過(guò)把阻塞代碼集中放入到其他一個(gè)或者多個(gè)進(jìn)程中去執(zhí)行,類似 Swoole 的 Task,不同的是 Mix 獲取執(zhí)行結(jié)果是同步編程方式,Mix 會(huì)封裝一個(gè)同步執(zhí)行器,在代碼中調(diào)用同步執(zhí)行器傳入一個(gè)閉包,閉包中包含阻塞IO調(diào)用代碼,調(diào)用后同步獲取結(jié)果(協(xié)程方式),該閉包的代碼將通過(guò) unixsocket 的方式傳遞到同步執(zhí)行器的進(jìn)程執(zhí)行,執(zhí)行完成后回傳結(jié)果。該同步執(zhí)行器進(jìn)程與其他 Server 一樣可自行添加代碼,可在啟動(dòng)時(shí)增加 -r 參數(shù)端口復(fù)用多開(kāi),Mix 通過(guò)這種方式將阻塞代碼集中在同步執(zhí)行器進(jìn)程中執(zhí)行,徹底避免阻塞帶來(lái)的影響。

解決這些問(wèn)題后,綜合考量單線程協(xié)程顯然更加符合 Mix 短小精悍、簡(jiǎn)單易用的定位,Mix V2.1 是截止現(xiàn)在唯一全面使用 Coroutine/Server 的框架。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容