請求集中在某些進程

現象

有時候我們透過命令php start.php status觀察到,請求被集中在特定的一些進程中處理,其他進程完全處於空閒狀態。

搶占機制

Workerman多個進程獲取連線的方式默認搶占式的,也就是說當客戶端發起連線時,所有空閒的進程都有機會去獲取這個連線,快者先得。到底誰快,是由作業系統核心調度決定的。作業系統可能會優先選取最近一次使用的進程獲得 CPU 使用權,因為 CPU 寄存器裡可能還存在上個進程的上下文資訊,這可以減少上下文切換開銷。所以當業務足夠快的時候或者壓測過程中,更容易出現連線集中被某些進程處理的情況,因為這個策略可以避免頻繁的進程切換,性能往往是最優的,並不是什麼問題。

輪詢機制

Workerman可以透過設置 $worker->reusePort = true; 的方式將獲取連線的方式改為輪詢的方式,輪詢的方式內核會將連線近似平均地分配給所有進程,這樣所有的進程將會一起處理請求。

誤區

很多開發者認為所有進程都參與請求處理性能越好,實際上不一定。當業務足夠簡單時,參與處理請求的進程數越趨近於 CPU 核心數伺服器吞吐量越高。例如4核伺服器,進程數設置為4時,helloworld壓測 QPS 一般是最高的。如果參與處理的進程數超過 CPU 核數太多,進程上下文開銷越大,性能反而越差。而一般帶數據庫業務時,進程數設置為 CPU 核數的3倍-6倍性能可能會更好。