Swoole TCP服務端與客戶端的 初步研究 持續更新
簡單TCP 服務端實現
server.php
<?php
$serv = new swoole_server('0.0.0.0', 9906);
$serv->set([
'worker_num' => 4, // 最大連接
'max_request' => 10000, // worker進程數
'log_level' => SWOOLE_LOG_ERROR, // 日誌等級 關閉開啓debug
'trace_flags' => SWOOLE_TRACE_SERVER, // 日誌等級 關閉開啓debug
]);
// 客戶端鏈接觸發
$serv->on('connect', function ($serv, $fd, $reactorId) {
echo "Client:{$reactorId} - {$fd} - Connect.\n";
});
// 接收函數
$serv->on('receive', function ($serv, $fd, $reactorId, $data) {
// echo 'cli:' . $data . "\n";
// 發送數據到客戶端
$serv->send($fd, "server: {$reactorId} - {$fd} - {$data}");
// $serv->close($fd);
});
$serv->on('close', function ($serv, $fd) {
echo "Client: Close.\n";
});
//啓動服務器
$serv->start();
如果想看是否真的啓動了配置中的最大連接數 可以執行以下命令查看
ps aft | grep server.php
set相關配置參數
名稱 | 參數值 | 描述 | 例 |
---|---|---|---|
最大連接 | max_conn |
此參數用來設置Server最大允許維持多少個tcp連接。超過此數量後,新進入的連接將被拒絕。此參數不要調整的過大,根據機器內存的實際情況來設置。底層會根據此數值一次性分配一塊大內存來保存Connection信息 |
max_conn => 10000 |
守護進程化 | daemonize |
加入此參數後,執行php server.php將轉入後臺作爲守護進程運行 | daemonize => 1 |
reactor線程數 | reactor_num |
通過此參數來調節Reactor線程的數量,以充分利用多核,reactor_num和默認設置爲CPU核數 | reactor_num => 2 |
worker進程數 | worker_num |
設置啓動的Worker進程數量。Swoole採用固定Worker進程的模式。全異步非阻塞服務器 worker_num配置爲CPU核數的1-4倍即可。同步阻塞服務器,worker_num配置爲100或者更高,具體要看每次請求處理的耗時和操作系統負載狀況。當設定的Worker進程數小於reactor線程數時,會自動調低reactor線程的數量 |
worker_num => 4 |
max_request | max_request |
此參數表示worker進程在處理完n次請求後結束運行。manager會重新創建一個worker進程。此選項用來防止worker進程內存溢出。PHP代碼也可以使用memory_get_usage來檢測進程的內存佔用情況,發現接近memory_limit時,調用exit()退出進程。manager進程會回收此進程,然後重新啓動一個新的Worker進程。onConnect/onClose不增加計數 設置爲0表示不自動重啓。在Worker進程中需要保存連接信息的服務,需要設置爲0. |
max_request => 2000 |
Listen隊列長度 | backlog |
此參數將決定最多同時有多少個待accept的連接,swoole本身accept效率是很高的,基本上不會出現大量排隊情況。 | backlog => 128 |
CPU親和設置 | open_cpu_affinity |
啓用CPU親和設置 | open_cpu_affinity => 1 |
TCP_NoDelay啓用 | open_tcp_nodelay |
啓用tcp_nodelay | open_tcp_nodelay => 1 |
TCP_DEFER_ACCEPT | tcp_defer_accept |
此參數設定一個秒數,當客戶端連接連接到服務器時,在約定秒數內並不會觸發accept,直到有數據發送,或者超時時纔會觸發。 | tcp_defer_accept => 5 |
日誌文件路徑 | log_file |
指定swoole錯誤日誌文件。在swoole運行期發生的異常信息會記錄到這個文件中。默認會打印到屏幕。 | log_file => ‘/data/log/swoole.log’ |
數據buffer | open_eof_check package_eof |
buffer主要是用於檢測數據是否完整,如果不完整swoole會繼續等待新的數據到來。直到收到完整的一個請求,纔會一次性發送給worker進程。這時onReceive會收到一個超過SW_BUFFER_SIZE,小於$serv->setting[‘package_max_length’]的數據。目前僅提供了EOF檢測、固定包頭長度檢測2種buffer模式。open_eof_check => true打開buffer package_eof => “\r\n\r\n” 設置EOF | open_eof_check => true package_eof => “\r\n\r\n” |
心跳檢測機制 | heartbeat_check_interval heartbeat_idle_time |
heartbeat_check_interval 每隔多少秒檢測一次,單位秒,Swoole會輪詢所有TCP連接,將超過心跳時間的連接關閉掉。heartbeat_idle_time TCP連接的最大閒置時間,單位s , 如果某fd最後一次發包距離現在的時間超過heartbeat_idle_time會把這個連接關閉。heartbeat_idle_time必須大於或等於heartbeat_check_interval |
heartbeat_check_interval => 30 heartbeat_idle_time => 60 |
worker進程數據包分配模式 | dispatch_mode |
1平均分配,2按FD取模固定分配,3搶佔式分配,默認爲取模(dispatch=2) | dispatch_mode=>1 |
簡單TCP 客戶端實現
Client.php
<?php
$client = new swoole_client(SWOOLE_SOCK_TCP); // 同步阻塞
$ret = $client->connect('127.0.0.1', 9906);
if (!$ret) {
exit("Connect Server fail.errCode={$client->errCode}");
}
fwrite(STDOUT, '請輸入:');
$msg = trim(fgets(STDIN));
$client->send($msg);
$result = $client->recv();
echo $result;
$client->close();