MixPHP V2.1 爲何從 Reactor+Manager+Worker 多進程改爲單線程協程

Mix V2.1 之前的版本一直採用與現在主流的 Swoole 框架一樣基於多進程 Swoole\Server 開發,V2.1 開始 Mix 全部基於 Swoole 的 Coroutine/Server 開發 (單線程協程),讓 Server 也可使用完全同步的編程方式,底層自動實現異步IO。

Reactor+Manager+Worker 多進程優缺點

Master+Worker 的進程模型是一種應用廣泛的傳統模型,像 Nginx、PHP-FPM 均採用這種模型,但 Swoole 的模型中多了一個 Manager 進程。

Swoole 進程模型

優點:

  • 可自行重啓:
    Reactor+Manager+Worker 進程架構最大的優點就是,當 Worker 出現任何異常,無需藉助第三方 (如:supervisor、pm2) 即可由程序本身的 Manager 進程重啓一個 Worker 進程。
  • 可利用多CPU:
    由於是多進程模型,Worker 進程執行在多個CPU中,因此可利用到多核。
  • 阻塞影響小:
    因爲 Reactor 多線程負責連接處理,而多個 Worker 進程負責執行 PHP 代碼,因此單個 Worker 的阻塞IO並不會影響其他請求 (協程模式,會影響到分配到該進程但沒有執行完成的請求)

缺點:

  • 編碼複雜、不夠靈活:
    Swoole\Server 在啓動前與啓動後 class 的屬性操作的作用域,對不熟悉的用戶非常不友好,容易掉坑,難以理解。處理一些全局業務時需要跨進程處理,帶來併發安全鎖的問題,且無法同時啓動多個 Server 或者自由的在代碼中隨意啓動停止 Server。
  • 平滑shutdown困難:
    由於程序執行在很多個 Worker 進程中,如果存在耗時任務,多進程模型很難精細的控制每個子進程執行完管道的全部請求,然後平滑有序的退出所有進程,Swoole\Server 雖然提供了 異步安全重啓特性 但是大部分框架是沒有處理 onWorkerExit 的,用戶也很難在框架基礎上擴展。

單線程協程優缺點

單線程模型在新創軟件領域非常流行,像 Redis、Node.js 都是單線程模型,而優缺點剛好與 Reactor+Manager+Worker 相反,但是 Mix 針對這些缺點提供瞭解決方案。

缺點:

  • 無法自行重啓:
    Mix V2.1 這個問題普遍存在於所有單進程程序中,包括 Golang、Node.js 開發的程序,在出現致命異常時都會導致進程退出,由於是單進程所以無法自行重啓,都需要藉助第三方 (如:supervisor、pm2)
  • 無法利用多CPU:
    由於是單進程模型,執行在一個CPU中,因此和 Node.js 一樣無法利用多核 (使用 docker 部署則無此問題)。
  • 阻塞影響大:
    單進程模型由於 Server 與業務邏輯一同執行在單個進程內,因此當遇到阻塞IO時,所有請求處理都會一起阻塞,導致響應時間變長,長時間的阻塞還會導致服務無法接收新的請求,Swoole 雖然 Hook 了大量的阻塞IO能支持協程,但還是有許多擴展是無法支持的,因此該問題最爲突出。

優點:

  • 編碼簡單、靈活:
    由於是單進程單線程模型,加上 Server 全部基於 Swoole 的 Coroutine/Server 開發,完全同步的編程方式,因此代碼非常簡單易懂。也沒有了多進程帶來的:跨進程對象屬性分歧問題,併發安全鎖問題,Server 也可隨意啓動 N 個、隨意停止。
  • 平滑shutdown簡單:
    單線程模型,處理信號只需處理一個進程,退出也只需處理一個進程,由於是同步編程方式,退出的處理邏輯也非常簡單易懂。

對缺點的解決方案

通過上面分析可以得出結論:單線程更加簡單靈活,但是最大的缺點就是阻塞問題,和多CPU利用問題,Mix V2.1 如何解決這些問題:

  • 多CPU利用:
    與 Node.js 解決該問題的方法一樣,通過多開進程來解決多CPU利用問題,由於同一個端口只能被一個程序綁定,因此多開只能綁定不同端口,勢必增加了反向代理的複雜度,但在 Linux v3.10 或更高版本內核中加入了端口複用功能,Mix 內置的 Server 只需啓動時增加 -r 參數即可在 Linux 中多開端口複用,達到與 Node.js 類似的解決多CPU利用的效果,查看範例

  • 阻塞:
    單進程單線程模型中要徹底解決 PHP 歷史遺留的阻塞IO問題,只能通過把阻塞代碼集中放入到其他一個或者多個進程中去執行,類似 Swoole 的 Task,不同的是 Mix 獲取執行結果是同步編程方式,Mix 會封裝一個同步執行器,在代碼中調用同步執行器傳入一個閉包,閉包中包含阻塞IO調用代碼,調用後同步獲取結果(協程方式),該閉包的代碼將通過 unixsocket 的方式傳遞到同步執行器的進程執行,執行完成後回傳結果。該同步執行器進程與其他 Server 一樣可自行添加代碼,可在啓動時增加 -r 參數端口複用多開,Mix 通過這種方式將阻塞代碼集中在同步執行器進程中執行,徹底避免阻塞帶來的影響。

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章