swoole教程第二節:基礎的通信實現-server篇-1

限於本人的技術水準不高,文章中若是有問題的地方但願各位老爺們可以告訴我。
今天說swoole的通信。
這個swoole的官網首頁已經有了例子,TCP Server和TCP Client
官網demo
實際上是四個步驟 官網詳細介紹php

  1. 構建Server對象html

  2. 設置運行時參數node

  3. 註冊事件回調函數mysql

  4. 啓動服務器react

其中 設置運行參數看這裏全部的設置參數
爲了方便你們看 ,我本身作了整理,看看就好web


<?php
//文件名 setConfig.php
//來源http://wiki.swoole.com/wiki/page/274.html
//如下內容有不對的請告訴我,萬分感謝
$setConfig = array();

// reactor線程數,reactor_num => 2,經過此參數來調節主進程內事件處理線程的數量,以充分利用多核。默認會啓用CPU核數相同的數量。
// reactor_num通常設置爲CPU核數的1-4倍,在swoole中reactor_num最大不得超過CPU核數*4。
// swoole的reactor線程是能夠利用多核,如:機器有128核,那麼swoole會啓動128線程。每一個線程能都會維持一個EventLoop。線程之間是無鎖的,
// 指令能夠被128核CPU並行執行。考慮到操做系統調度存在必定程度的誤差,能夠設置爲CPU核數*2,以便最大化利用CPU的每個核。
$setConfig['reactor_num']=2;




// 設置啓動的worker進程數。
// 業務代碼是全異步非阻塞的,這裏設置爲CPU的1-4倍最合理
// 業務代碼爲同步阻塞,須要根據請求響應時間和系統負載來調整
// 好比1個請求耗時100ms,要提供1000QPS的處理能力,那必須配置100個進程或更多。
// 但開的進程越多,佔用的內存就會大大增長,並且進程間切換的開銷就會愈來愈大。因此這裏適立即可。不要配置過大。
// 每一個進程佔用40M內存,那100個進程就須要佔用4G內存
$setConfig['worker_num']=4;





// 設置worker進程的最大任務數。一個worker進程在處理完超過此數值的任務後將自動退出。這個參數是爲了防止PHP進程內存溢出。
// 若是不但願進程自動退出能夠設置爲0
// 當worker進程內發生致命錯誤或者人工執行exit時,進程會自動退出。主進程會從新啓動一個新的worker進程來處理任務
$setConfig['max_request']=2000;





// 服務器程序,最大容許的鏈接數,如max_conn => 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].
// 此參數不要調整的過大,根據機器內存的實際狀況來設置。Swoole會根據此數值一次性分配一塊大內存來保存Connection信息
$setConfig['max_conn']=10000;











// 配置task進程的數量,配置此參數後將會啓用task功能。因此swoole_server務必要註冊onTask/onFinish2個事件回調函數。若是沒有註冊,服務器程序將沒法啓動。
// task進程是同步阻塞的,配置方式與worker同步模式一致。
// task進程內不能使用swoole_server->task方法
// task進程內不能使用mysql-async/redis-async/swoole_event等異步IO函數
$setConfig['task_worker_num']=2;








// 設置task進程與worker進程之間通訊的方式。
// 1, 使用unix socket通訊
// 2, 使用消息隊列通訊
// 3, 使用消息隊列通訊,並設置爲爭搶模式
// 設置爲3後,task/taskwait將沒法指定目標進程ID
$setConfig['task_ipc_mode']=3;




// 設置task進程的最大任務數。一個task進程在處理完超過此數值的任務後將自動退出。
// 這個參數是爲了防止PHP進程內存溢出。若是不但願進程自動退出能夠設置爲0。
// task_max_request默認爲5000,受swoole_config.h的SW_MAX_REQUEST宏控制
// 1.7.17以上版本默認值調整爲0,不會主動退出進程
$setConfig['task_max_request']=5000;








// 設置task的數據臨時目錄,在swoole_server中,若是投遞的數據超過8192字節,
// 將啓用臨時文件來保存數據。這裏的task_tmpdir就是用來設置臨時文件保存的位置。
// 須要swoole-1.7.7+
$setConfig['task_tmpdir']="/tmp/tasl_tmpdir/";//路徑我是隨便寫的







// 數據包分發策略。能夠選擇3種類型,默認爲2
// 1,輪循模式,收到會輪循分配給每個worker進程
// 2,固定模式,根據鏈接的文件描述符分配worker。這樣能夠保證同一個鏈接發來的數據只會被同一個worker處理
// 3,搶佔模式,主進程會根據Worker的忙閒狀態選擇投遞,只會投遞給處於閒置狀態的Worker
// 4,IP分配,根據TCP/UDP鏈接的來源IP進行取模hash,分配給一個固定的worker進程。
// 能夠保證同一個來源IP的鏈接數據總會被分配到同一個worker進程
// 5,UID分配,須要用戶代碼中調用$serv->bind() 將一個鏈接綁定1個uid。而後swoole根據UID的值分配到不一樣的worker進程
// dispatch_mode 4,5兩種模式,在 1.7.8以上版本可用
// dispatch_mode=1/3時,底層會屏蔽onConnect/onClose事件,緣由是這2種模式下沒法保證onConnect/onClose/onReceive的順序
// 非請求響應式的服務器程序,請不要使用模式1或3
// SWOOLE_BASE模式
// dispatch_mode 配置在BASE模式是無效的,由於BASE不存在投遞任務。
// 當reactor收到客戶端發來的數據後會當即回調onReceive,不須要投遞Worker進程。
$setConfig['dispatch_mode']=2;










// 設置消息隊列的KEY,僅在ipc_mode = 2或task_ipc_mode = 2時使用。
// 設置的Key僅做爲隊列的基數。此參數的默認值爲ftok($php_script_file, 1)。實際使用的消息隊列KEY爲:
// recv數據消息隊列KEY爲 message_queue_key
// send數據消息隊列KEY爲 message_queue_key + 1
// task數據消息隊列KEY爲 message_queue_key + 2
// recv/send數據隊列在server結束後,會自動銷燬。
// task隊列在server結束後不會銷燬,從新啓動程序後,task進程仍然會接着處理隊列中的任務。
// 1.7.8之前的版本,KEY會+serv->master_pid。增長pid是爲了防止服務器程序重啓,致使複用上一次的消息隊列數據,讀取到錯誤的數據
$setConfig['message_queue_key']=2;








// 守護進程化。設置daemonize => 1時,程序將轉入後臺做爲守護進程運行。長時間運行的服務器端程序必須啓用此項。
// 若是不啓用守護進程,當ssh終端退出後,程序將被終止運行。
// 啓用守護進程後,標準輸入和輸出會被重定向到 log_file
// 若是未設置log_file,將重定向到 /dev/null,全部打印屏幕的信息都會被丟棄
$setConfig['daemonize']=1;





// Listen隊列長度,如backlog => 128,此參數將決定最多同時有多少個等待accept的鏈接。
// 與php-fpm/apache等軟件不一樣,swoole並不依賴backlog來解決鏈接排隊的問題。因此不須要設置太大的backlog參數。
$setConfig['backlog']= 128;




// log_file => '/data/log/swoole.log', 指定swoole錯誤日誌文件。
// 在swoole運行期發生的異常信息會記錄到這個文件中。默認會打印到屏幕。
// 注意log_file不會自動切分文件,因此須要按期清理此文件。
// 觀察log_file的輸出,能夠獲得服務器的各種異常信息和警告。
// log_file中的日誌僅僅是作運行時錯誤記錄,沒有長久存儲的必要。
// 開啓守護進程模式後(daemonize => true),標準輸出將會被重定向到log_file。
// 在PHP代碼中echo/var_dump/print等打印到屏幕的內容會寫入到log_file文件
$setConfig['log_file']='/data/log/swoole.log';




// 啓用心跳檢測,此選項表示每隔多久輪循一次,單位爲秒。
// 如 heartbeat_check_interval => 60,表示每60秒,遍歷全部鏈接,若是該鏈接在60秒內,沒有向服務器發送任何數據,此鏈接將被強制關閉。
// swoole_server並不會主動向客戶端發送心跳包,而是被動等待客戶端發送心跳。
// 服務器端的heartbeat_check僅僅是檢測鏈接上一次發送數據的時間,若是超過限制,將切斷鏈接。
// heartbeat_check僅支持TCP鏈接
$setConfig['heartbeat_check_interval']=60;


// 與heartbeat_check_interval配合使用。表示鏈接最大容許空閒的時間。如
// array(
// 'heartbeat_idle_time' => 600,
// 'heartbeat_check_interval' => 60,
// );
// 表示每60秒遍歷一次,一個鏈接若是600秒內未向服務器發送任何數據,此鏈接將被強制關閉。
$setConfig['heartbeat_idle_time']=600;





// 打開EOF檢測,此選項將檢測客戶端鏈接發來的數據,當數據包結尾是指定的字符串時纔會投遞給Worker進程。
// 不然會一直拼接數據包,直到超過緩存區或者超時纔會停止。當出錯時swoole底層會認爲是惡意鏈接,丟棄數據並強制關閉鏈接。
// array(
// 'open_eof_check' => true, //打開EOF檢測
// 'package_eof' => "\r\n", //設置EOF
// )
// 常見的Memcache/SMTP/POP等協議都是以\r\n結束的,就可使用此配置。
//開啓後能夠保證Worker進程一次性老是收到一個或者多個完整的數據包。

// EOF檢測不會從數據中間查找eof字符串,因此Worker進程可能會同時收到多個數據包,
// 須要在應用層代碼中自行explode("\r\n", $data) 來拆分數據包
// 1.7.15版本增長了open_eof_split,支持從數據中查找EOF,並切分數據
$setConfig['open_eof_check']=1;



// package_eof
// 與open_eof_check配合使用,設置EOF字符串。
// package_eof最大隻容許傳入8個字節的字符串
$setConfig['package_eof']="\r\n";






// open_eof_split
// 啓用EOF自動分包。當設置open_eof_check後,底層檢測數據是否以特定的字符串結尾來進行數據緩衝。
// 但默認只截取收到數據的末尾部分作對比。這時候可能會產生多條數據合併在一個包內。

// 啓用open_eof_split參數後,底層會從數據包中間查找EOF,並拆分數據包。
// onReceive每次僅收到一個以EOF字串結尾的數據包。
// open_eof_split在1.7.15以上版本可用
$setConfig['open_eof_split']=1;



// 打開包長檢測特性。包長檢測提供了固定包頭+包體這種格式協議的解析。
// 啓用後,能夠保證Worker進程onReceive每次都會收到一個完整的數據包。
$setConfig['open_length_check']=1;





// s :有符號、主機字節序、2字節短整型
// S:無符號、主機字節序、2字節短整型
// n:無符號、網絡字節序、2字節短整型
// N:無符號、網絡字節序、4字節整型
// l:有符號、主機字節序、2字節短整型(小寫L)
// L:無符號、主機字節序、2字節短整型(大寫L)

$setConfig['package_length_type']='s';




// 設置最大數據包尺寸,開啓open_length_check/open_eof_check/open_http_protocol等協議解析後。
// swoole底層會進行數據包拼接。這時在數據包未收取完整時,全部數據都是保存在內存中的。

// 因此須要設定package_max_length,一個數據包最大容許佔用的內存尺寸。
// 若是同時有1萬個TCP鏈接在發送數據,每一個數據包2M,那麼最極限的狀況下,就會佔用20G的內存空間。

// open_length_check,當發現包長度超過package_max_length,將直接丟棄此數據,並關閉鏈接,不會佔用任何內存。
// open_eof_check,由於沒法事先得知數據包長度,因此收到的數據仍是會保存到內存中,持續增加。
// 當發現內存佔用已超過package_max_length時,將直接丟棄此數據,並關閉鏈接
// open_http_protocol,GET請求最大容許8K,並且沒法修改配置。
// POST請求會檢測Content-Length,若是Content-Length超過package_max_length,將直接丟棄此數據,發送http 400錯誤,並關閉鏈接
// 此參數不宜設置過大,不然會佔用很大的內存
$setConfig['package_max_length']=2;




// 啓用CPU親和性設置。在多核的硬件平臺中,啓用此特性會將swoole的reactor線程/worker進程綁定到固定的一個核上。
//能夠避免進程/線程的運行時在多個核之間互相切換,提升CPU Cache的命中率。
// 使用taskset命令查看進程的CPU親和設置:
// taskset -p 進程ID
// pid 24666's current affinity mask: f
// pid 24901's current affinity mask: 8
// mask是一個掩碼數字,按bit計算每bit對應一個CPU核,若是某一位爲0表示綁定此核,進程會被調度到此CPU上,爲0表示進程不會被調度到此CPU。
// 示例中pid爲24666的進程mask = f 表示未綁定到CPU,操做系統會將此進程調度到任意一個CPU核上。
// pid爲24901的進程mask = 8,8轉爲二進制是 1000,表示此進程綁定在第4個CPU核上。
// 僅推薦在全異步非阻塞的Server程序中啓用
$setConfig['open_cpu_affinity']=1;




// IO密集型程序中,全部網絡中斷都是用CPU0來處理,若是網絡IO很重,CPU0負載太高會致使網絡中斷沒法及時處理,那網絡收發包的能力就會降低。
// 若是不設置此選項,swoole將會使用所有CPU核,底層根據reactor_id或worker_id與CPU核數取模來設置CPU綁定。
// 若是內核與網卡有多隊列特性,網絡中斷會分佈到多核,能夠緩解網絡中斷的壓力
// 此選項必須與open_cpu_affinity同時設置纔會生效
// array('cpu_affinity_ignore' => array(0, 1))
// 接受一個數組做爲參數,array(0, 1) 表示不使用CPU0,CPU1,專門空出來處理網絡中斷。
$setConfig['cpu_affinity_ignore']=array(0, 1);





// open_tcp_nodelay
// 啓用open_tcp_nodelay,開啓後TCP鏈接發送數據時會關閉Nagle合併算法,
// 當即發往客戶端鏈接。在某些場景下,如http服務器,能夠提高響應速度
$setConfig['open_tcp_nodelay']=1;





//啓用tcp_defer_accept特性,能夠設置爲一個數值,表示當一個TCP鏈接有數據發送時才觸發accept。
$setConfig['tcp_defer_accept']=5;




// 設置SSL隧道加密,設置值爲一個文件名字符串,制定cert證書和key的路徑。
$setConfig['ssl_cert_file']='/config/ssl.crt';
$setConfig['ssl_key_file']='/config//ssl.key';




// 設置worker/task子進程的所屬用戶。服務器若是須要監聽1024如下的端口,
// 必須有root權限。但程序運行在root用戶下,代碼中一旦有漏洞,攻擊者就能夠以root的方式執行遠程指令,風險很大。
// 配置了user項以後,可讓主進程運行在root權限下,子進程運行在普通用戶權限下。
// 此配置在swoole-1.7.9以上版本可用
// 僅在使用root用戶啓動時有效
$setConfig['user']='apache';
// 設置worker/task子進程的進程用戶組。與user配置相同,此配置是修改進程所屬用戶組,提高服務器程序的安全性。
$setConfig['group']='www-data';
// 重定向Worker進程的文件系統根目錄。此設置可使進程對文件系統的讀寫與實際的操做系統文件系統隔離。提高安全性
$setConfig['chroot']='/data/server/';







// 調整管道通訊的內存緩存區長度。swoole的reactor線程與worker進程之間使用unix socket進行通訊,
// 在收發大量數據的場景下,須要啓用內存緩存隊列。此函數能夠修改內存緩存的長度。
// 此參數在1.7.17以上版本默認爲32M,1.7.17如下版本默認爲8M
$setConfig['pipe_buffer_size']=2;







// 此配置影響swoole 2個方面
// 數據發送緩存區
// 調整鏈接發送緩存區的大小。TCP通訊有擁塞控制機制,服務器向客戶端發送大量數據時,並不能當即發出。這時發送的數據會存放在服務器端的內存緩存區內。此參數能夠調整內存緩存區的大小。
// 若是發送數據過多,客戶端阻塞,數據佔滿緩存區後Server會報以下錯誤信息:
// swFactoryProcess_finish: send failed, session#1 output buffer has been overflowed.
// swoole_server->send大小
// 調用 swoole_server->send, swoole_http_server->end/write,swoole_websocket_server->push 時,最大發送的數據不得超過 buffer_output_size 配置。
// buffer_output_size默認爲2M,緩存區塞滿後send將會失敗
// 注意此函數不該當調整過大,避免擁塞的數據過多,致使吃光機器內存
// 開啓大量worker進程時,將會佔用worker_num * buffer_output_size 字節的內存
$setConfig['buffer_output_size']=2;//




// enable_unsafe_event
// swoole在配置dispatch_mode=1或3後,由於系統沒法保證onConnect/onReceive/onClose的順序,默認關閉了onConnect/onClose事件。

// 若是應用程序須要onConnect/onClose事件,而且能接受順序問題可能帶來的安全風險,
//能夠經過設置 enable_unsafe_event = true,啓用onConnect/onClose事件

// enable_unsafe_event配置在1.7.18以上版本可用

$setConfig['enable_unsafe_event']=1;




// swoole在配置dispatch_mode=1或3後,系統沒法保證onConnect/onReceive/onClose的順序,所以可能會有一些請求數據在鏈接關閉後,才能到達Worker進程。
// discard_timeout_request配置默認爲true,表示若是worker進程收到了已關閉鏈接的數據請求,將自動丟棄。
// discard_timeout_request若是設置爲false,表示不管鏈接是否關閉Worker進程都會處理數據請求。
$setConfig['discard_timeout_request']=1;



配置項目以後該說回調函數了,我也作了一些整理redis

<?php
//文件名 OnEvent.php
/// 來源 http://wiki.swoole.com/wiki/page/41.html
//不是全部回調都要寫,由於有些回調函數須要有相關的配置項目開啓才能生效
//這個文件的目的是告訴有哪些回調函數,用途是什麼,以及觀察swoole的觸發流程
$serv->on('Start', function (swoole_server $server){//僅容許echo、打印Log、修改進程名稱。不得執行其餘操做。
// 已建立了manager進程
// 已建立了worker子進程
// 已監聽全部TCP/UDP端口
// 已監聽了定時器
// 接下來要執行
// 主Reactor開始接收事件,客戶端能夠connect到Server
    echo PHP_EOL;
    echo " start";
    echo PHP_EOL;
    var_dump($server);
    echo PHP_EOL;
});




$serv->on('Shutdown', function (swoole_server $server){
// 在此以前Swoole Server已進行了以下操做
// 已關閉全部線程
// 已關閉全部worker進程
// 已close全部TCP/UDP監聽端口
// 已關閉主Rector
// 強制kill進程不會回調onShutdown,如kill -9
// 須要使用kill -15來發送SIGTREM信號到主進程才能按照正常的流程終止
     echo PHP_EOL;
    echo " shutdown";
    var_dump($server);

    echo PHP_EOL;
});




$serv->on('WorkerStart', function (swoole_server $server,  $worker_id){// 不能寫 int $worker_id
//此事件在worker進程/task進程啓動時發生。這裏建立的對象能夠在進程生命週期內使用
    echo PHP_EOL;
    echo " WorkerStart";
    echo PHP_EOL;
    var_dump($worker_id);
    echo PHP_EOL;
});




$serv->on('WorkerStop', function (swoole_server $server, int $worker_id){
//此事件在worker進程終止時發生。在此函數中能夠回收worker進程申請的各種資源
// $worker_id是一個從0-$worker_num之間的數字,表示這個worker進程的ID
// $worker_id和進程PID沒有任何關係
    echo PHP_EOL;
    echo " WorkerStop";
    var_dump($worker_id);
    echo PHP_EOL;
});





//定時器觸發
$serv->on('Timer', function (swoole_server $server, int $interval) {
// $interval是定時器時間間隔,根據$interval的值來區分是哪一個定時器觸發的。這裏的定時器是由$serv->addtimer來添加的,是固定間隔循環觸發的。
// onTimer中執行時間過長,會致使下一次定時延緩觸發。如設定1秒的定時器,1秒後會觸發onTimer,onTimer函數用時1.5s,那麼第二次觸發onTimer的時間爲第3秒。中間第2秒的定時器會被丟棄
// onTimer回調函數若是要執行一個耗時操做,最好是使用$serv->task投遞到task進程池中執行
    echo PHP_EOL;
    echo " Timer";
    var_dump($interval);
    echo PHP_EOL;
});





$serv->on('connect',function (swoole_server $server,  $fd,  $from_id){
// $server是swoole_server對象
// $fd是鏈接的文件描述符,發送數據/關閉鏈接時須要此參數
// $from_id來自那個Reactor線程
// $server是swoole_server對象
// $fd是鏈接的文件描述符,發送數據/關閉鏈接時須要此參數
// $from_id來自那個Reactor線程
// onConnect/onClose這2個回調發生在worker進程內,而不是主進程。
// UDP協議下只有onReceive事件,沒有onConnect/onClose事件
    echo PHP_EOL;
    echo " connect";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
});




//接收到數據時回調此函數,發生在worker進程中
$serv->on('Receive',function (swoole_server $server,  $fd,  $from_id,  $data){
// $server,swoole_server對象
// $fd,TCP客戶端鏈接的文件描述符
// $from_id,TCP鏈接所在的Reactor線程ID
// $data,收到的數據內容,多是文本或者二進制內容
//詳情  http://wiki.swoole.com/wiki/page/50.html
    echo PHP_EOL;
    echo " Receive";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
});





//接收到UDP數據包時回調此函數,發生在worker進程中。
$serv->on('Packet',function (swoole_server $server, string $data, array $client_info){
// $server,swoole_server對象
// $data,收到的數據內容,多是文本或者二進制內容
// $client_info,客戶端信息包括address/port/server_socket 3項數據
// 服務器同時監聽TCP/UDP端口時,收到TCP協議的數據會回調onReceive,收到UDP數據包回調onPacket
    echo PHP_EOL;
    echo " Packet";
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
    var_dump($client_info);
    echo PHP_EOL;
});



//TCP客戶端鏈接關閉後,在worker進程中回調此函數
$serv->on('Close',function (swoole_server $server, int $fd, int $from_id){
// $server是swoole_server對象
// $fd是鏈接的文件描述符
// $from_id來自那個reactor線程
// 注意:這裏回調onClose時表示客戶端鏈接已經關閉,因此無需執行$server->close($fd)。代碼中執行$serv->close($fd) 會拋出PHP錯誤告警。
    echo PHP_EOL;
    echo " Close";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
});



//在task_worker進程內被調用。worker進程可使用swoole_server_task函數向task_worker進程投遞新的任務
$serv->on('Task',function (swoole_server $serv, int $task_id, int $from_id, string $data){
// $task_id是任務ID,由swoole擴展內自動生成,用於區分不一樣的任務。
//$task_id和$from_id組合起來纔是全局惟一的,不一樣的worker進程投遞的任務ID可能會有相同
// $from_id來自於哪一個worker進程
// $data 是任務的內容
// 返回執行結果到worker進程
// 1.7.2以上的版本,在onTask函數中 return字符串,表示將此內容返回給worker進程。
//worker進程中會觸發onFinish函數,表示投遞的task已完成。
    echo PHP_EOL;
    echo " Task";
    echo PHP_EOL;
    var_dump($task_id);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
});





//當worker進程投遞的任務在task_worker中完成時,task進程會經過swoole_server->finish()方法將任務處理的結果發送給worker進程。
$serv->on('Finish',function (swoole_server $serv, int $task_id, string $data){
// $task_id是任務的ID
// $data是任務處理的結果內容
// task進程的onTask事件中沒有調用finish方法或者return結果。worker進程不會觸發onFinish
    echo PHP_EOL;
    echo " Finish";
    echo PHP_EOL;
    var_dump($task_id);
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
});



//當工做進程收到由sendMessage發送的管道消息時會觸發onPipeMessage事件。worker/task進程均可能會觸發onPipeMessage事件
$serv->on('PipeMessage',function (swoole_server $server, int $from_worker_id, string $message){
    echo PHP_EOL;
    echo " PipeMessage";
    echo PHP_EOL;
    var_dump($from_worker_id);
    echo PHP_EOL;
    var_dump($message);
    echo PHP_EOL;
});



//當worker/task_worker進程發生異常後會在Manager進程內回調此函數
$serv->on('WorkerError',function (swoole_server $serv, int $worker_id, int $worker_pid, int $exit_code){
// $worker_id是異常進程的編號
// $worker_pid是異常進程的ID
// $exit_code退出的狀態碼,範圍是 1 ~255
// 此函數主要用於報警和監控,一旦發現Worker進程異常退出,
// 那麼頗有多是遇到了致命錯誤或者進程CoreDump。經過記錄日誌或者發送報警的信息來提示開發者進行相應的處理。
    echo PHP_EOL;
    echo " WorkerError";
    echo PHP_EOL;
    var_dump($from_worker_id);
    echo PHP_EOL;
    var_dump($worker_pid);
    echo PHP_EOL;
    var_dump($exit_code);
    echo PHP_EOL;
});





//當管理進程啓動時調用它,函數原型:
$serv->on('ManagerStart',function (swoole_server $serv){
// 在這個回調函數中能夠修改管理進程的名稱。
// 注意manager進程中不能添加定時器
// manager進程中能夠調用task功能
    echo PHP_EOL;
    echo " ManagerStart";
    echo PHP_EOL;
});





//當管理進程結束時調用它,函數原型:
$serv->on('ManagerStop',function (swoole_server $serv){
    echo PHP_EOL;
    echo " ManagerStop";
    echo PHP_EOL;
});



呼,終於寫完了,我整理這兩個文件的目的是方便你們本身測試,官網有文檔,我作的只是代碼化。算法

當我把這些所有看一遍以後,我對swoole_server有了大致印象,好比worker,好比task等等。
來,上個圖sql

圖片看不到,看這裏apache

http://wiki.swoole.com/wiki/page/2.html

swoole.jpgprocess.jpg



下面開始我最喜歡的環節 ,跑程序

server.php

<?php
$host  = "127.0.0.1";
$port  = 9501;//$port監聽的端口,如9501,監聽小於1024端口須要root權限,若是此端口被佔用server->start時會失敗
$serv = new swoole_server( $host,  $port);
$serv->set(array(
     'worker_num' => 3,   //工做進程數量
 ));
include 'OnEvent.php';
$serv->start();

client.php

<?php
$client = new swoole_client(SWOOLE_SOCK_TCP, SWOOLE_SOCK_ASYNC);
//設置事件回調函數
$client->on("connect", function($cli) {
    $cli->send("hello world\n");
});
$client->on("receive", function($cli, $data){
    echo "Received: ".$data."\n";
});
$client->on("error", function($cli){
    echo "Connect failed\n";
});
$client->on("close", function($cli){
    echo "Connection close\n";
});
//發起網絡鏈接
$client->connect('127.0.0.1', 9501, 0.5);

我在server.php裏引入了OnEvent.php(我寫上了全部的回調函數)
我想看看,server作了什麼
來,開始

php server.php

運行結果

start
object(swoole_server)#1 (4) {
  ["connections"]=>
  object(swoole_connection_iterator)#2 (0) {
  }
  ["setting"]=>
  array(5) {
    ["worker_num"]=>
    int(3)
    ["task_worker_num"]=>
    int(0)
    ["pipe_buffer_size"]=>
    int(33554432)
    ["buffer_output_size"]=>
    int(2097152)
    ["max_connection"]=>
    int(65536)
  }
  ["master_pid"]=>
  int(7418)
  ["manager_pid"]=>
  int(7420)
}


 WorkerStart
int(0)


 WorkerStart
int(1)


 ManagerStart

 WorkerStart
int(2)

程序並無死,上面的是回調函數裏面的輸出
server先是 執行start,而後按照設置的worker_num的數目建立worker觸發WorkerStart的回調,同時建立Manager執行了ManagerStart
咱們再看看上面的兩個圖片,結合server的運行結果,想必會更多一些瞭解
我以爲兩個圖畫的很好,讓我再看一遍。

好的,順便的,看到了server的屬性

object(swoole_server)#1 (4) {
  ["connections"]=>//看這裏 http://wiki.swoole.com/wiki/page/427.html
  object(swoole_connection_iterator)#2 (0) {
  }
  ["setting"]=>//看這裏  http://wiki.swoole.com/wiki/page/157.html
  array(5) {
    ["worker_num"]=>
    int(3)
    ["task_worker_num"]=>
    int(0)
    ["pipe_buffer_size"]=>
    int(33554432)
    ["buffer_output_size"]=>
    int(2097152)
    ["max_connection"]=>
    int(65536)
  }
  ["master_pid"]=>//看這裏   http://wiki.swoole.com/wiki/page/154.html
  int(7418)
  ["manager_pid"]=>//看這裏  http://wiki.swoole.com/wiki/page/155.html
  int(7420)
}

由於配置的沒寫task,而且當前沒有客戶端連上來,這裏還有一些屬性沒有展現出來
你們詳細的看這裏 屬性列表

好的,讓咱們運行客戶端

php client.php

connect
int(1) //  這個是 fd

int(0)// 這個是 from_id


 Receive
int(1)//  這個是 fd

int(0)// 這個是 from_id

string(12) "hello world
"// 這個是 data

這裏貼出來 server端多出來的內容

補充一下:對一個對象使用get_class_methods能夠得到對象的全部方法,今天忘了怎麼獲取客戶端ip地址了,用這個查了一下,是server的connection_info方法

好的,但願你們用多測試測試,觀察server的變化,體會swoole的server調用
結合運行結果來看流程圖

今天暫時到這裏,哪裏我說的不對,請你們指正,我也是一個學習中的人

相關文章
相關標籤/搜索