reactor_num
Reactor線程數,reactor_num => 2,通過此參數來調節主進程內事件處理線程的數量,以充分利用多核。默認會啓用CPU核數相同的數量。reactor_num一般設置為CPU核數的1-4倍,在swoole中reactor_num最大不得超過CPU核數*4。swoole的Reactor線程是可以利用多核,如:機器有128核,那麼底層會啓動128線程。每個線程能都會維持一個EventLoop。線程之間是無鎖的,指令可以被128核CPU並行執行。考慮到操作系統調度存在一定程度的性能損失,可以設置為CPU核數*2,以便最大化利用CPU的每一個核。
reactor_num必須小於或等於worker_num。如果設置的reactor_num大於worker_num,那麼swoole會自動調整使reactor_num等於worker_num
1.7.14以上版本在超過8核的機器上reactor_num默認設置為8
worker_num
設置啓動的worker進程數。
- 業務代碼是全異步非阻塞的,這裏設置為CPU的
1-4
- 倍最合理
- 業務代碼為同步阻塞,需要根據請求響應時間和系統負載來調整
比如1個請求耗時100ms,要提供1000QPS的處理能力,那必須配置100個進程或更多。但開的進程越多,佔用的內存就會大大增加,而且進程間切換的開銷就會越來越大。所以這裏適當即可。不要配置過大。
- 每個進程佔用
40M
- 內存,那
100
- 個進程就需要佔用
4G
- 內存
max_request
設置worker進程的最大任務數,默認為0,一個worker進程在處理完超過此數值的任務後將自動退出,進程退出後會釋放所有內存和資源。
這個參數的主要作用是解決PHP進程內存溢出問題。PHP應用程序有緩慢的內存泄漏,但無法定位到具體原因、無法解決,可以通過設置max_request解決。max_request
- 只能用於同步阻塞、無狀態的請求響應式服務器程序
- 在swoole中真正維持客户端TCP連接的是master進程,worker進程僅處理客户端發送來的請求,因為客户端是不需要感知Worker進程重啓的
- 純異步的Server不應當設置
max_request
- 使用Base模式時
max_request
- 是無效的
當worker進程內發生致命錯誤或者人工執行exit時,進程會自動退出。master進程會重新啓動一個新的worker進程來繼續處理請求
max_conn (max_connection)
服務器程序,最大允許的連接數,如max_connection => 10000, 此參數用來設置Server最大允許維持多少個TCP連接。超過此數量後,新進入的連接將被拒絕。max_connection
- 最大不得超過操作系統
ulimit -n
- 的值,否則會報一條警告信息,並重置為
ulimit -n
- 的值
max_connection
- 默認值為
ulimit -n
- 的值
WARN swServer_start_check: serv->max_conn is exceed the maximum value[100000].
最大上限
底層使用了SESSION_LIST來實現session_id(虛擬fd)與真實fd的對應,因此除了max_sockets限制之外,max_connection還受限於SW_SESSION_LIST_SIZE宏的設置。目前SW_SESSION_LIST_SIZE底層的值為1M,請勿設置max_connection超過1M
內存佔用
max_connection參數不要調整的過大,根據機器內存的實際情況來設置。Swoole會根據此數值一次性分配一塊大內存來保存Connection信息,可使用gdb跟蹤運行中的進程,打印p sizeof(swConnection) 得到準確的數值。在1.9.16版本中一個TCP連接的Connection信息,需要佔用224字節。
最小設置
此選項設置過小底層會拋出錯誤,並設置為ulimit -n的值。
最小值為(serv->worker_num + SwooleG.task_worker_num) * 2 + 32
serv->max_connection is too small.
dispatch_mode
數據包分發策略。可以選擇3種類型,默認為2
- 1,輪循模式,收到會輪循分配給每一個worker進程
- 2,固定模式,根據連接的文件描述符分配worker。這樣可以保證同一個連接發來的數據只會被同一個worker處理
- 3,搶佔模式,主進程會根據Worker的忙閒狀態選擇投遞,只會投遞給處於閒置狀態的Worker
- 4,IP分配,根據客户端IP進行取模hash,分配給一個固定的worker進程。可以保證同一個來源IP的連接數據總會被分配到同一個worker進程。算法為
ip2long(ClientIP) % worker_num
- 5,UID分配,需要用户代碼中調用 $serv-> bind() 將一個連接綁定1個uid。然後swoole根據UID的值分配到不同的worker進程。算法為
UID % worker_num
- ,如果需要使用字符串作為UID,可以使用
crc32(UID_STRING)
使用建議
- 無狀態
Server
- 可以使用
1
- 或
3
- ,同步阻塞
Server
- 使用
3
- ,異步非阻塞
Server
- 使用
1
- 有狀態使用
2
- 、
4
- 、
5
dispatch_mode 4,5兩種模式,在1.7.8以上版本可用
dispatch_mode=1/3時,底層會屏蔽onConnect/onClose事件,原因是這2種模式下無法保證onConnect/onClose/onReceive的順序
非請求響應式的服務器程序,請不要使用模式1或3
UDP協議
dispatch_mode=2/4/5
- 時為固定分配,底層使用客户端IP取模散列到不同的worker進程,算法為
ip2long(ClientIP) % worker_numdispatch_mode=1/3
- 時隨機分配到不同的worker進程
BASE模式
dispatch_mode配置在BASE模式是無效的,因為BASE不存在投遞任務,當Reactor線程收到客户端發來的數據後會立即在當前線程/進程回調onReceive,不需要投遞Worker進程。
daemonize
守護進程化。設置daemonize => 1時,程序將轉入後台作為守護進程運行。長時間運行的服務器端程序必須啓用此項。
如果不啓用守護進程,當ssh終端退出後,程序將被終止運行。
- 啓用守護進程後,標準輸入和輸出會被重定向到
log_file
- 如果未設置
log_file
- ,將重定向到
/dev/null
- ,所有打印屏幕的信息都會被丟棄
- 啓用守護進程後,
CWD
- (當前目錄)環境變量的值會發生變更,相對路徑的文件讀寫會出錯。PHP程序中必須使用絕對路徑
systemd
使用systemd管理Swoole服務時,請勿設置daemonize = 1。主要原因是systemd的機制與init不同。init進程的PID為1,程序使用daemonize後,會脱離終端,最終被init進程託管,與init關係變為父子進程關係。但systemd是啓動了一個單獨的後台進程,自行fork管理其他服務進程,因此不需要daemonize,反而使用了daemonize = 1會使得Swoole程序與該管理進程失去父子進程關係。
- systemd
-