1. 程式人生 > 實用技巧 >Swoole從入門到入土(3)——TCP伺服器[基本配置項]

Swoole從入門到入土(3)——TCP伺服器[基本配置項]

在這一節的開篇,讓我們先解決上一節的“配置”話題。對於server物件,有很多配置項決定了服務端的行為,可以用set的函式進行配置的設定。

1、函式set:用於設定執行時的各項引數。伺服器啟動後通過 $serv->setting 來訪問 Server->set 方法設定的引數陣列。

Swoole\Server->set(array $setting): void

$setting:配置項陣列。

注意:函式set必須在 Server->start() 前呼叫。

示例:

$server->set(array(
    'reactor_num'   => 2,     //
reactor thread num 'worker_num' => 4, // worker process num 'backlog' => 128, // listen backlog 'max_request' => 50, 'dispatch_mode' => 1, ));

每個配置項的意義,下面會進行介紹。

2、常用配置項

1) 屬性reactor_num:設定啟動的 Reactor 執行緒數。【預設值:CPU 核數】什麼是reactor執行緒呢?點選這裡檢視上一節常識科普

說明:

通過此引數來調節主程序內事件處理執行緒的數量,以充分利用多核。預設會啟用 CPU 核數相同的數量。

Reactor 執行緒是可以利用多核,如:機器有 128 核,那麼底層會啟動 128 執行緒。
每個執行緒能都會維持一個 EventLoop。執行緒之間是無鎖的,指令可以被 128 核 CPU 並行執行。
考慮到作業系統排程存在一定程度的效能損失,可以設定為 CPU 核數 * 2,以便最大化利用 CPU 的每一個核。

建議設定為 CPU 核數的 1-4 倍,但最大不得超過 swoole_cpu_num() * 4。

2)worker_num:設定啟動的 Worker 程序數。【預設值:CPU 核數】什麼是Worker程序呢?點選這裡檢視上一節常識科普

說明:

如果業務程式碼是全非同步 IO 的,這裡設定為 CPU 核數的 1-4 倍最合理。

如果業務程式碼為同步 IO,需要根據請求響應時間和系統負載來調整,例如:100-500
預設設定為 swoole_cpu_num(),最大不得超過 swoole_cpu_num() * 1000
假設每個程序佔用 40M 記憶體,100 個程序就需要佔用 4G 記憶體,如何正確檢視程序的記憶體佔用請參考 Swoole 官方視訊教程

舉例:

如 1 個請求耗時 100ms,要提供 1000QPS 的處理能力,那必須配置 100 個程序或更多。
但開的程序越多,佔用的記憶體就會大大增加,而且程序間切換的開銷就會越來越大。所以這裡適當即可。不要配置過大。

3) max_request:設定 worker 程序的最大任務數。【預設值:0 即不會退出程序】

說明:

一個 worker 程序在處理完超過此數值的任務後將自動退出,程序退出後會釋放所有記憶體和資源。

這個引數的主要作用是解決由於程式編碼不規範導致的 PHP 程序記憶體洩露問題。PHP 應用程式有緩慢的記憶體洩漏,但無法定位到具體原因、無法解決,可以通過設定 max_request 臨時解決,但是專案要持久執行還是必須找到記憶體洩漏的程式碼並修復。

達到 max_request 不一定馬上關閉程序,參考 max_wait_time。

SWOOLE_BASE 下,達到 max_request 重啟程序會導致客戶端連線斷開。

當 worker 程序內發生致命錯誤或者人工執行 exit 時,程序會自動退出。master 程序會重新啟動一個新的 worker 程序來繼續處理請求。

4) max_wait_time:設定 Worker 程序收到停止服務通知後最大等待時間【預設值:3】

說明:

經常會碰到由於 worker 阻塞卡頓導致 worker 無法正常 reload, 無法滿足一些生產場景,例如釋出程式碼熱更新需要 reload 程序。所以,我們加入了程序重啟超時時間的選項。

管理程序收到重啟、關閉訊號後或者達到 max_request 時,管理程序會重起該 worker 程序。分以下幾個步驟:

· 底層會增加一個 (max_wait_time) 秒的定時器,觸發定時器後,檢查程序是否依然存在,如果是,會強制殺掉,重新拉一個程序。

· 需要在 onWorkerStop 回撥裡面做收尾工作,需要在 max_wait_time 秒內做完收尾。

· 依次向目標程序傳送 SIGTERM 訊號,殺掉程序。

5) backlog:設定 Listen 佇列長度

舉例:

如 backlog => 128,此引數將決定最多同時有多少個等待 accept 的連線。

說明:

關於 TCP 的 backlog

· 我們知道 TCP 有三次握手的過程,客戶端 syn=>服務端 syn+ack=>客戶端 ack,當伺服器收到客戶端的 ack 後會將連線放到一個叫做 accept queue 的佇列裡面(linux2.2 之後握手過程分為 syn queue 和 accept queue 兩個佇列,syn queue 長度由 tcp_max_syn_backlog 決定)

· 佇列的大小由 backlog 引數和配置 somaxconn 的最小值決定,我們可以通過 ss -lt 命令檢視最終的 accept queue 佇列大小,Swoole 的主程序呼叫 accept(高版本核心呼叫的是 accept4,為了節省一次 set no block 系統呼叫)

· 從 accept queue 裡面取走。 當 accept queue 滿了之後連線有可能成功(成功是通過 TCP 的重傳機制,相關的配置有 tcp_synack_retries 和 tcp_abort_on_overflow)

· 也有可能失敗,失敗後客戶端的表現就是連線被重置(客戶端收到 syn+ack 包就認為連線成功了,實際上服務端還處於半連線狀態,有可能傳送 rst 包給客戶端,客戶端的表現就是 Connection reset by peer

· 或者連線超時,而服務端會記錄失敗的記錄,可以通過 netstat -s|grep 'times the listen queue of a socket overflowed 來檢視日誌。如果出現了上述現象,你就應該調大該值了。 幸運的是 Swoole 的 SWOOLE_PROCESS 模式與 PHP-FPM/Apache 等軟體不同,並不依賴 backlog 來解決連線排隊的問題。所以基本不會遇到上述現象。

6) dispatch_mode:資料包分發策略。【預設值:2】

說明:

建議:

無狀態 Server 可以使用 1 或 3,同步阻塞 Server 使用 3,非同步非阻塞 Server 使用 1

有狀態使用 2、4、5

在UDP模式下:

dispatch_mode=2/4/5 時為固定分配,底層使用客戶端 IP 取模雜湊到不同的 Worker 程序,演算法為 ip2long(ClientIP) % worker_num

dispatch_mode=1/3 時隨機分配到不同的 Worker 程序

dispatch_mode 配置在 SWOOLE_BASE 模式是無效的,因為 BASE 不存在投遞任務,當收到客戶端發來的資料後會立即在當前執行緒 / 程序回撥 onReceive,不需要投遞 Worker 程序。

注意:

dispatch_mode=1/3 時,底層會遮蔽 onConnect/onClose 事件,原因是這 2 種模式下無法保證 onConnect/onClose/onReceive 的順序;

非請求響應式的伺服器程式,請不要使用模式 1 或 3。例如:http 服務就是響應式的,可以使用 1 或 3,有 TCP 長連線狀態的就不能使用 1 或 3。

Swoole最基本配置項就以上這些啦,這一篇到這裡就結束了,其它的配置項,包括重啟、心跳機制會在之後的文章中慢慢介紹。大家下期見

--------------------------- 我是可愛的分割線 ----------------------------

最後博主借地宣傳一下,漳州程式設計小組招新了,這是一個面向漳州青少年資訊學/軟體設計的學習小組,有意向的同學點選連結,聯絡我吧。