国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

swoole教程第二節(jié):基礎(chǔ)的通訊實(shí)現(xiàn)-server篇-1

lemanli / 2757人閱讀

摘要:主進(jìn)程會(huì)重新啟動(dòng)一個(gè)新的進(jìn)程來(lái)處理任務(wù)服務(wù)器程序,最大允許的連接數(shù),如此參數(shù)用來(lái)設(shè)置最大允許維持多少個(gè)連接。如果沒(méi)有注冊(cè),服務(wù)器程序?qū)o(wú)法啟動(dòng)。增加是為了防止服務(wù)器程序重啟,導(dǎo)致復(fù)用上一次的消息隊(duì)列數(shù)據(jù),讀取到錯(cuò)誤的數(shù)據(jù)守護(hù)進(jìn)程化。

限于本人的技術(shù)水準(zhǔn)不高,文章中如果有問(wèn)題的地方希望各位老爺們能夠告訴我。
今天說(shuō)swoole的通訊。
這個(gè)swoole的官網(wǎng)首頁(yè)已經(jīng)有了例子,TCP Server和TCP Client
官網(wǎng)demo
其實(shí)是四個(gè)步驟 官網(wǎng)詳細(xì)介紹

構(gòu)建Server對(duì)象

設(shè)置運(yùn)行時(shí)參數(shù)

注冊(cè)事件回調(diào)函數(shù)

啟動(dòng)服務(wù)器

其中 設(shè)置運(yùn)行參數(shù)看這里所有的設(shè)置參數(shù)
為了方便大家看 ,我自己做了整理,看看就好


 2,通過(guò)此參數(shù)來(lái)調(diào)節(jié)主進(jìn)程內(nèi)事件處理線程的數(shù)量,以充分利用多核。默認(rèn)會(huì)啟用CPU核數(shù)相同的數(shù)量。
// reactor_num一般設(shè)置為CPU核數(shù)的1-4倍,在swoole中reactor_num最大不得超過(guò)CPU核數(shù)*4。
// swoole的reactor線程是可以利用多核,如:機(jī)器有128核,那么swoole會(huì)啟動(dòng)128線程。每個(gè)線程能都會(huì)維持一個(gè)EventLoop。線程之間是無(wú)鎖的,
// 指令可以被128核CPU并行執(zhí)行。考慮到操作系統(tǒng)調(diào)度存在一定程度的偏差,可以設(shè)置為CPU核數(shù)*2,以便最大化利用CPU的每一個(gè)核。
$setConfig["reactor_num"]=2;




// 設(shè)置啟動(dòng)的worker進(jìn)程數(shù)。
// 業(yè)務(wù)代碼是全異步非阻塞的,這里設(shè)置為CPU的1-4倍最合理
// 業(yè)務(wù)代碼為同步阻塞,需要根據(jù)請(qǐng)求響應(yīng)時(shí)間和系統(tǒng)負(fù)載來(lái)調(diào)整
// 比如1個(gè)請(qǐng)求耗時(shí)100ms,要提供1000QPS的處理能力,那必須配置100個(gè)進(jìn)程或更多。
// 但開(kāi)的進(jìn)程越多,占用的內(nèi)存就會(huì)大大增加,而且進(jìn)程間切換的開(kāi)銷就會(huì)越來(lái)越大。所以這里適當(dāng)即可。不要配置過(guò)大。
// 每個(gè)進(jìn)程占用40M內(nèi)存,那100個(gè)進(jìn)程就需要占用4G內(nèi)存
$setConfig["worker_num"]=4;





// 設(shè)置worker進(jìn)程的最大任務(wù)數(shù)。一個(gè)worker進(jìn)程在處理完超過(guò)此數(shù)值的任務(wù)后將自動(dòng)退出。這個(gè)參數(shù)是為了防止PHP進(jìn)程內(nèi)存溢出。
// 如果不希望進(jìn)程自動(dòng)退出可以設(shè)置為0
// 當(dāng)worker進(jìn)程內(nèi)發(fā)生致命錯(cuò)誤或者人工執(zhí)行exit時(shí),進(jìn)程會(huì)自動(dòng)退出。主進(jìn)程會(huì)重新啟動(dòng)一個(gè)新的worker進(jìn)程來(lái)處理任務(wù)
$setConfig["max_request"]=2000;





// 服務(wù)器程序,最大允許的連接數(shù),如max_conn => 10000, 此參數(shù)用來(lái)設(shè)置Server最大允許維持多少個(gè)tcp連接。超過(guò)此數(shù)量后,新進(jìn)入的連接將被拒絕。
// max_connection最大不得超過(guò)操作系統(tǒng)ulimit -n的值,否則會(huì)報(bào)一條警告信息,并重置為ulimit -n的值
// max_connection默認(rèn)值為ulimit -n的值
// WARN    swServer_start_check: serv->max_conn is exceed the maximum value[100000].
// 此參數(shù)不要調(diào)整的過(guò)大,根據(jù)機(jī)器內(nèi)存的實(shí)際情況來(lái)設(shè)置。Swoole會(huì)根據(jù)此數(shù)值一次性分配一塊大內(nèi)存來(lái)保存Connection信息
$setConfig["max_conn"]=10000;











// 配置task進(jìn)程的數(shù)量,配置此參數(shù)后將會(huì)啟用task功能。所以swoole_server務(wù)必要注冊(cè)onTask/onFinish2個(gè)事件回調(diào)函數(shù)。如果沒(méi)有注冊(cè),服務(wù)器程序?qū)o(wú)法啟動(dòng)。
// task進(jìn)程是同步阻塞的,配置方式與worker同步模式一致。
// task進(jìn)程內(nèi)不能使用swoole_server->task方法
// task進(jìn)程內(nèi)不能使用mysql-async/redis-async/swoole_event等異步IO函數(shù)
$setConfig["task_worker_num"]=2;








// 設(shè)置task進(jìn)程與worker進(jìn)程之間通信的方式。
// 1, 使用unix socket通信
// 2, 使用消息隊(duì)列通信
// 3, 使用消息隊(duì)列通信,并設(shè)置為爭(zhēng)搶模式
// 設(shè)置為3后,task/taskwait將無(wú)法指定目標(biāo)進(jìn)程ID
$setConfig["task_ipc_mode"]=3;




// 設(shè)置task進(jìn)程的最大任務(wù)數(shù)。一個(gè)task進(jìn)程在處理完超過(guò)此數(shù)值的任務(wù)后將自動(dòng)退出。
// 這個(gè)參數(shù)是為了防止PHP進(jìn)程內(nèi)存溢出。如果不希望進(jìn)程自動(dòng)退出可以設(shè)置為0。
// task_max_request默認(rèn)為5000,受swoole_config.h的SW_MAX_REQUEST宏控制
// 1.7.17以上版本默認(rèn)值調(diào)整為0,不會(huì)主動(dòng)退出進(jìn)程
$setConfig["task_max_request"]=5000;








// 設(shè)置task的數(shù)據(jù)臨時(shí)目錄,在swoole_server中,如果投遞的數(shù)據(jù)超過(guò)8192字節(jié),
// 將啟用臨時(shí)文件來(lái)保存數(shù)據(jù)。這里的task_tmpdir就是用來(lái)設(shè)置臨時(shí)文件保存的位置。
// 需要swoole-1.7.7+
$setConfig["task_tmpdir"]="/tmp/tasl_tmpdir/";//路徑我是隨便寫(xiě)的







// 數(shù)據(jù)包分發(fā)策略。可以選擇3種類型,默認(rèn)為2
// 1,輪循模式,收到會(huì)輪循分配給每一個(gè)worker進(jìn)程
// 2,固定模式,根據(jù)連接的文件描述符分配worker。這樣可以保證同一個(gè)連接發(fā)來(lái)的數(shù)據(jù)只會(huì)被同一個(gè)worker處理
// 3,搶占模式,主進(jìn)程會(huì)根據(jù)Worker的忙閑狀態(tài)選擇投遞,只會(huì)投遞給處于閑置狀態(tài)的Worker
// 4,IP分配,根據(jù)TCP/UDP連接的來(lái)源IP進(jìn)行取模hash,分配給一個(gè)固定的worker進(jìn)程。
// 可以保證同一個(gè)來(lái)源IP的連接數(shù)據(jù)總會(huì)被分配到同一個(gè)worker進(jìn)程
// 5,UID分配,需要用戶代碼中調(diào)用$serv->bind() 將一個(gè)連接綁定1個(gè)uid。然后swoole根據(jù)UID的值分配到不同的worker進(jìn)程
// dispatch_mode 4,5兩種模式,在 1.7.8以上版本可用
// dispatch_mode=1/3時(shí),底層會(huì)屏蔽onConnect/onClose事件,原因是這2種模式下無(wú)法保證onConnect/onClose/onReceive的順序
// 非請(qǐng)求響應(yīng)式的服務(wù)器程序,請(qǐng)不要使用模式1或3
// SWOOLE_BASE模式
// dispatch_mode 配置在BASE模式是無(wú)效的,因?yàn)锽ASE不存在投遞任務(wù)。
// 當(dāng)reactor收到客戶端發(fā)來(lái)的數(shù)據(jù)后會(huì)立即回調(diào)onReceive,不需要投遞Worker進(jìn)程。
$setConfig["dispatch_mode"]=2;










// 設(shè)置消息隊(duì)列的KEY,僅在ipc_mode = 2或task_ipc_mode = 2時(shí)使用。
// 設(shè)置的Key僅作為隊(duì)列的基數(shù)。此參數(shù)的默認(rèn)值為ftok($php_script_file, 1)。實(shí)際使用的消息隊(duì)列KEY為:
// recv數(shù)據(jù)消息隊(duì)列KEY為 message_queue_key
// send數(shù)據(jù)消息隊(duì)列KEY為 message_queue_key + 1
// task數(shù)據(jù)消息隊(duì)列KEY為 message_queue_key + 2
// recv/send數(shù)據(jù)隊(duì)列在server結(jié)束后,會(huì)自動(dòng)銷毀。
// task隊(duì)列在server結(jié)束后不會(huì)銷毀,重新啟動(dòng)程序后,task進(jìn)程仍然會(huì)接著處理隊(duì)列中的任務(wù)。
// 1.7.8以前的版本,KEY會(huì)+serv->master_pid。增加pid是為了防止服務(wù)器程序重啟,導(dǎo)致復(fù)用上一次的消息隊(duì)列數(shù)據(jù),讀取到錯(cuò)誤的數(shù)據(jù)
$setConfig["message_queue_key"]=2;








// 守護(hù)進(jìn)程化。設(shè)置daemonize => 1時(shí),程序?qū)⑥D(zhuǎn)入后臺(tái)作為守護(hù)進(jìn)程運(yùn)行。長(zhǎng)時(shí)間運(yùn)行的服務(wù)器端程序必須啟用此項(xiàng)。
// 如果不啟用守護(hù)進(jìn)程,當(dāng)ssh終端退出后,程序?qū)⒈唤K止運(yùn)行。
// 啟用守護(hù)進(jìn)程后,標(biāo)準(zhǔn)輸入和輸出會(huì)被重定向到 log_file
// 如果未設(shè)置log_file,將重定向到 /dev/null,所有打印屏幕的信息都會(huì)被丟棄
$setConfig["daemonize"]=1;





// Listen隊(duì)列長(zhǎng)度,如backlog => 128,此參數(shù)將決定最多同時(shí)有多少個(gè)等待accept的連接。
// 與php-fpm/apache等軟件不同,swoole并不依賴backlog來(lái)解決連接排隊(duì)的問(wèn)題。所以不需要設(shè)置太大的backlog參數(shù)。
$setConfig["backlog"]= 128;




// log_file => "/data/log/swoole.log", 指定swoole錯(cuò)誤日志文件。
// 在swoole運(yùn)行期發(fā)生的異常信息會(huì)記錄到這個(gè)文件中。默認(rèn)會(huì)打印到屏幕。
// 注意log_file不會(huì)自動(dòng)切分文件,所以需要定期清理此文件。
// 觀察log_file的輸出,可以得到服務(wù)器的各類異常信息和警告。
// log_file中的日志僅僅是做運(yùn)行時(shí)錯(cuò)誤記錄,沒(méi)有長(zhǎng)久存儲(chǔ)的必要。
// 開(kāi)啟守護(hù)進(jìn)程模式后(daemonize => true),標(biāo)準(zhǔn)輸出將會(huì)被重定向到log_file。
// 在PHP代碼中echo/var_dump/print等打印到屏幕的內(nèi)容會(huì)寫(xiě)入到log_file文件
$setConfig["log_file"]="/data/log/swoole.log";




// 啟用心跳檢測(cè),此選項(xiàng)表示每隔多久輪循一次,單位為秒。
// 如 heartbeat_check_interval => 60,表示每60秒,遍歷所有連接,如果該連接在60秒內(nèi),沒(méi)有向服務(wù)器發(fā)送任何數(shù)據(jù),此連接將被強(qiáng)制關(guān)閉。
// swoole_server并不會(huì)主動(dòng)向客戶端發(fā)送心跳包,而是被動(dòng)等待客戶端發(fā)送心跳。
// 服務(wù)器端的heartbeat_check僅僅是檢測(cè)連接上一次發(fā)送數(shù)據(jù)的時(shí)間,如果超過(guò)限制,將切斷連接。
// heartbeat_check僅支持TCP連接
$setConfig["heartbeat_check_interval"]=60;


// 與heartbeat_check_interval配合使用。表示連接最大允許空閑的時(shí)間。如
// array(
// "heartbeat_idle_time" => 600,
// "heartbeat_check_interval" => 60,
// );
// 表示每60秒遍歷一次,一個(gè)連接如果600秒內(nèi)未向服務(wù)器發(fā)送任何數(shù)據(jù),此連接將被強(qiáng)制關(guān)閉。
$setConfig["heartbeat_idle_time"]=600;





// 打開(kāi)EOF檢測(cè),此選項(xiàng)將檢測(cè)客戶端連接發(fā)來(lái)的數(shù)據(jù),當(dāng)數(shù)據(jù)包結(jié)尾是指定的字符串時(shí)才會(huì)投遞給Worker進(jìn)程。
// 否則會(huì)一直拼接數(shù)據(jù)包,直到超過(guò)緩存區(qū)或者超時(shí)才會(huì)中止。當(dāng)出錯(cuò)時(shí)swoole底層會(huì)認(rèn)為是惡意連接,丟棄數(shù)據(jù)并強(qiáng)制關(guān)閉連接。
// array(
// "open_eof_check" => true, //打開(kāi)EOF檢測(cè)
// "package_eof" => "
", //設(shè)置EOF
// )
// 常見(jiàn)的Memcache/SMTP/POP等協(xié)議都是以
結(jié)束的,就可以使用此配置。
//開(kāi)啟后可以保證Worker進(jìn)程一次性總是收到一個(gè)或者多個(gè)完整的數(shù)據(jù)包。

// EOF檢測(cè)不會(huì)從數(shù)據(jù)中間查找eof字符串,所以Worker進(jìn)程可能會(huì)同時(shí)收到多個(gè)數(shù)據(jù)包,
// 需要在應(yīng)用層代碼中自行explode("
", $data) 來(lái)拆分?jǐn)?shù)據(jù)包
// 1.7.15版本增加了open_eof_split,支持從數(shù)據(jù)中查找EOF,并切分?jǐn)?shù)據(jù)
$setConfig["open_eof_check"]=1;



// package_eof
// 與open_eof_check配合使用,設(shè)置EOF字符串。
// package_eof最大只允許傳入8個(gè)字節(jié)的字符串
$setConfig["package_eof"]="
";






// open_eof_split
// 啟用EOF自動(dòng)分包。當(dāng)設(shè)置open_eof_check后,底層檢測(cè)數(shù)據(jù)是否以特定的字符串結(jié)尾來(lái)進(jìn)行數(shù)據(jù)緩沖。
// 但默認(rèn)只截取收到數(shù)據(jù)的末尾部分做對(duì)比。這時(shí)候可能會(huì)產(chǎn)生多條數(shù)據(jù)合并在一個(gè)包內(nèi)。

// 啟用open_eof_split參數(shù)后,底層會(huì)從數(shù)據(jù)包中間查找EOF,并拆分?jǐn)?shù)據(jù)包。
// onReceive每次僅收到一個(gè)以EOF字串結(jié)尾的數(shù)據(jù)包。
// open_eof_split在1.7.15以上版本可用
$setConfig["open_eof_split"]=1;



// 打開(kāi)包長(zhǎng)檢測(cè)特性。包長(zhǎng)檢測(cè)提供了固定包頭+包體這種格式協(xié)議的解析。
// 啟用后,可以保證Worker進(jìn)程onReceive每次都會(huì)收到一個(gè)完整的數(shù)據(jù)包。
$setConfig["open_length_check"]=1;





// s :有符號(hào)、主機(jī)字節(jié)序、2字節(jié)短整型
// S:無(wú)符號(hào)、主機(jī)字節(jié)序、2字節(jié)短整型
// n:無(wú)符號(hào)、網(wǎng)絡(luò)字節(jié)序、2字節(jié)短整型
// N:無(wú)符號(hào)、網(wǎng)絡(luò)字節(jié)序、4字節(jié)整型
// l:有符號(hào)、主機(jī)字節(jié)序、2字節(jié)短整型(小寫(xiě)L)
// L:無(wú)符號(hào)、主機(jī)字節(jié)序、2字節(jié)短整型(大寫(xiě)L)

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




// 設(shè)置最大數(shù)據(jù)包尺寸,開(kāi)啟open_length_check/open_eof_check/open_http_protocol等協(xié)議解析后。
// swoole底層會(huì)進(jìn)行數(shù)據(jù)包拼接。這時(shí)在數(shù)據(jù)包未收取完整時(shí),所有數(shù)據(jù)都是保存在內(nèi)存中的。

// 所以需要設(shè)定package_max_length,一個(gè)數(shù)據(jù)包最大允許占用的內(nèi)存尺寸。
// 如果同時(shí)有1萬(wàn)個(gè)TCP連接在發(fā)送數(shù)據(jù),每個(gè)數(shù)據(jù)包2M,那么最極限的情況下,就會(huì)占用20G的內(nèi)存空間。

// open_length_check,當(dāng)發(fā)現(xiàn)包長(zhǎng)度超過(guò)package_max_length,將直接丟棄此數(shù)據(jù),并關(guān)閉連接,不會(huì)占用任何內(nèi)存。
// open_eof_check,因?yàn)闊o(wú)法事先得知數(shù)據(jù)包長(zhǎng)度,所以收到的數(shù)據(jù)還是會(huì)保存到內(nèi)存中,持續(xù)增長(zhǎng)。
// 當(dāng)發(fā)現(xiàn)內(nèi)存占用已超過(guò)package_max_length時(shí),將直接丟棄此數(shù)據(jù),并關(guān)閉連接
// open_http_protocol,GET請(qǐng)求最大允許8K,而且無(wú)法修改配置。
// POST請(qǐng)求會(huì)檢測(cè)Content-Length,如果Content-Length超過(guò)package_max_length,將直接丟棄此數(shù)據(jù),發(fā)送http 400錯(cuò)誤,并關(guān)閉連接
// 此參數(shù)不宜設(shè)置過(guò)大,否則會(huì)占用很大的內(nèi)存
$setConfig["package_max_length"]=2;




// 啟用CPU親和性設(shè)置。在多核的硬件平臺(tái)中,啟用此特性會(huì)將swoole的reactor線程/worker進(jìn)程綁定到固定的一個(gè)核上。
//可以避免進(jìn)程/線程的運(yùn)行時(shí)在多個(gè)核之間互相切換,提高CPU Cache的命中率。
// 使用taskset命令查看進(jìn)程的CPU親和設(shè)置:
// taskset -p 進(jìn)程ID
// pid 24666"s current affinity mask: f
// pid 24901"s current affinity mask: 8
// mask是一個(gè)掩碼數(shù)字,按bit計(jì)算每bit對(duì)應(yīng)一個(gè)CPU核,如果某一位為0表示綁定此核,進(jìn)程會(huì)被調(diào)度到此CPU上,為0表示進(jìn)程不會(huì)被調(diào)度到此CPU。
// 示例中pid為24666的進(jìn)程mask = f 表示未綁定到CPU,操作系統(tǒng)會(huì)將此進(jìn)程調(diào)度到任意一個(gè)CPU核上。
// pid為24901的進(jìn)程mask = 8,8轉(zhuǎn)為二進(jìn)制是 1000,表示此進(jìn)程綁定在第4個(gè)CPU核上。
// 僅推薦在全異步非阻塞的Server程序中啟用
$setConfig["open_cpu_affinity"]=1;




// IO密集型程序中,所有網(wǎng)絡(luò)中斷都是用CPU0來(lái)處理,如果網(wǎng)絡(luò)IO很重,CPU0負(fù)載過(guò)高會(huì)導(dǎo)致網(wǎng)絡(luò)中斷無(wú)法及時(shí)處理,那網(wǎng)絡(luò)收發(fā)包的能力就會(huì)下降。
// 如果不設(shè)置此選項(xiàng),swoole將會(huì)使用全部CPU核,底層根據(jù)reactor_id或worker_id與CPU核數(shù)取模來(lái)設(shè)置CPU綁定。
// 如果內(nèi)核與網(wǎng)卡有多隊(duì)列特性,網(wǎng)絡(luò)中斷會(huì)分布到多核,可以緩解網(wǎng)絡(luò)中斷的壓力
// 此選項(xiàng)必須與open_cpu_affinity同時(shí)設(shè)置才會(huì)生效
// array("cpu_affinity_ignore" => array(0, 1))
// 接受一個(gè)數(shù)組作為參數(shù),array(0, 1) 表示不使用CPU0,CPU1,專門(mén)空出來(lái)處理網(wǎng)絡(luò)中斷。
$setConfig["cpu_affinity_ignore"]=array(0, 1);





// open_tcp_nodelay
// 啟用open_tcp_nodelay,開(kāi)啟后TCP連接發(fā)送數(shù)據(jù)時(shí)會(huì)關(guān)閉Nagle合并算法,
// 立即發(fā)往客戶端連接。在某些場(chǎng)景下,如http服務(wù)器,可以提升響應(yīng)速度
$setConfig["open_tcp_nodelay"]=1;





//啟用tcp_defer_accept特性,可以設(shè)置為一個(gè)數(shù)值,表示當(dāng)一個(gè)TCP連接有數(shù)據(jù)發(fā)送時(shí)才觸發(fā)accept。
$setConfig["tcp_defer_accept"]=5;




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




// 設(shè)置worker/task子進(jìn)程的所屬用戶。服務(wù)器如果需要監(jiān)聽(tīng)1024以下的端口,
// 必須有root權(quán)限。但程序運(yùn)行在root用戶下,代碼中一旦有漏洞,攻擊者就可以以root的方式執(zhí)行遠(yuǎn)程指令,風(fēng)險(xiǎn)很大。
// 配置了user項(xiàng)之后,可以讓主進(jìn)程運(yùn)行在root權(quán)限下,子進(jìn)程運(yùn)行在普通用戶權(quán)限下。
// 此配置在swoole-1.7.9以上版本可用
// 僅在使用root用戶啟動(dòng)時(shí)有效
$setConfig["user"]="apache";
// 設(shè)置worker/task子進(jìn)程的進(jìn)程用戶組。與user配置相同,此配置是修改進(jìn)程所屬用戶組,提升服務(wù)器程序的安全性。
$setConfig["group"]="www-data";
// 重定向Worker進(jìn)程的文件系統(tǒng)根目錄。此設(shè)置可以使進(jìn)程對(duì)文件系統(tǒng)的讀寫(xiě)與實(shí)際的操作系統(tǒng)文件系統(tǒng)隔離。提升安全性
$setConfig["chroot"]="/data/server/";







// 調(diào)整管道通信的內(nèi)存緩存區(qū)長(zhǎng)度。swoole的reactor線程與worker進(jìn)程之間使用unix socket進(jìn)行通信,
// 在收發(fā)大量數(shù)據(jù)的場(chǎng)景下,需要啟用內(nèi)存緩存隊(duì)列。此函數(shù)可以修改內(nèi)存緩存的長(zhǎng)度。
// 此參數(shù)在1.7.17以上版本默認(rèn)為32M,1.7.17以下版本默認(rèn)為8M
$setConfig["pipe_buffer_size"]=2;







// 此配置影響swoole 2個(gè)方面
// 數(shù)據(jù)發(fā)送緩存區(qū)
// 調(diào)整連接發(fā)送緩存區(qū)的大小。TCP通信有擁塞控制機(jī)制,服務(wù)器向客戶端發(fā)送大量數(shù)據(jù)時(shí),并不能立即發(fā)出。這時(shí)發(fā)送的數(shù)據(jù)會(huì)存放在服務(wù)器端的內(nèi)存緩存區(qū)內(nèi)。此參數(shù)可以調(diào)整內(nèi)存緩存區(qū)的大小。
// 如果發(fā)送數(shù)據(jù)過(guò)多,客戶端阻塞,數(shù)據(jù)占滿緩存區(qū)后Server會(huì)報(bào)如下錯(cuò)誤信息:
// swFactoryProcess_finish: send failed, session#1 output buffer has been overflowed.
// swoole_server->send大小
// 調(diào)用 swoole_server->send, swoole_http_server->end/write,swoole_websocket_server->push 時(shí),最大發(fā)送的數(shù)據(jù)不得超過(guò) buffer_output_size 配置。
// buffer_output_size默認(rèn)為2M,緩存區(qū)塞滿后send將會(huì)失敗
// 注意此函數(shù)不應(yīng)當(dāng)調(diào)整過(guò)大,避免擁塞的數(shù)據(jù)過(guò)多,導(dǎo)致吃光機(jī)器內(nèi)存
// 開(kāi)啟大量worker進(jìn)程時(shí),將會(huì)占用worker_num * buffer_output_size 字節(jié)的內(nèi)存
$setConfig["buffer_output_size"]=2;//




// enable_unsafe_event
// swoole在配置dispatch_mode=1或3后,因?yàn)橄到y(tǒng)無(wú)法保證onConnect/onReceive/onClose的順序,默認(rèn)關(guān)閉了onConnect/onClose事件。

// 如果應(yīng)用程序需要onConnect/onClose事件,并且能接受順序問(wèn)題可能帶來(lái)的安全風(fēng)險(xiǎn),
//可以通過(guò)設(shè)置 enable_unsafe_event = true,啟用onConnect/onClose事件

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

$setConfig["enable_unsafe_event"]=1;




// swoole在配置dispatch_mode=1或3后,系統(tǒng)無(wú)法保證onConnect/onReceive/onClose的順序,因此可能會(huì)有一些請(qǐng)求數(shù)據(jù)在連接關(guān)閉后,才能到達(dá)Worker進(jìn)程。
// discard_timeout_request配置默認(rèn)為true,表示如果worker進(jìn)程收到了已關(guān)閉連接的數(shù)據(jù)請(qǐng)求,將自動(dòng)丟棄。
// discard_timeout_request如果設(shè)置為false,表示無(wú)論連接是否關(guān)閉Worker進(jìn)程都會(huì)處理數(shù)據(jù)請(qǐng)求。
$setConfig["discard_timeout_request"]=1;



配置項(xiàng)目之后該說(shuō)回調(diào)函數(shù)了,我也做了一些整理

on("Start", function (swoole_server $server){//僅允許echo、打印Log、修改進(jìn)程名稱。不得執(zhí)行其他操作。
// 已創(chuàng)建了manager進(jìn)程
// 已創(chuàng)建了worker子進(jìn)程
// 已監(jiān)聽(tīng)所有TCP/UDP端口
// 已監(jiān)聽(tīng)了定時(shí)器
// 接下來(lái)要執(zhí)行
// 主Reactor開(kāi)始接收事件,客戶端可以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已進(jìn)行了如下操作
// 已關(guān)閉所有線程
// 已關(guān)閉所有worker進(jìn)程
// 已close所有TCP/UDP監(jiān)聽(tīng)端口
// 已關(guān)閉主Rector
// 強(qiáng)制kill進(jìn)程不會(huì)回調(diào)onShutdown,如kill -9
// 需要使用kill -15來(lái)發(fā)送SIGTREM信號(hào)到主進(jìn)程才能按照正常的流程終止
     echo PHP_EOL;
    echo " shutdown";
    var_dump($server);

    echo PHP_EOL;
});




$serv->on("WorkerStart", function (swoole_server $server,  $worker_id){// 不能寫(xiě) int $worker_id
//此事件在worker進(jìn)程/task進(jìn)程啟動(dòng)時(shí)發(fā)生。這里創(chuàng)建的對(duì)象可以在進(jìn)程生命周期內(nèi)使用
    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進(jìn)程終止時(shí)發(fā)生。在此函數(shù)中可以回收worker進(jìn)程申請(qǐng)的各類資源
// $worker_id是一個(gè)從0-$worker_num之間的數(shù)字,表示這個(gè)worker進(jìn)程的ID
// $worker_id和進(jìn)程PID沒(méi)有任何關(guān)系
    echo PHP_EOL;
    echo " WorkerStop";
    var_dump($worker_id);
    echo PHP_EOL;
});





//定時(shí)器觸發(fā)
$serv->on("Timer", function (swoole_server $server, int $interval) {
// $interval是定時(shí)器時(shí)間間隔,根據(jù)$interval的值來(lái)區(qū)分是哪個(gè)定時(shí)器觸發(fā)的。這里的定時(shí)器是由$serv->addtimer來(lái)添加的,是固定間隔循環(huán)觸發(fā)的。
// onTimer中執(zhí)行時(shí)間過(guò)長(zhǎng),會(huì)導(dǎo)致下一次定時(shí)延緩觸發(fā)。如設(shè)定1秒的定時(shí)器,1秒后會(huì)觸發(fā)onTimer,onTimer函數(shù)用時(shí)1.5s,那么第二次觸發(fā)onTimer的時(shí)間為第3秒。中間第2秒的定時(shí)器會(huì)被丟棄
// onTimer回調(diào)函數(shù)如果要執(zhí)行一個(gè)耗時(shí)操作,最好是使用$serv->task投遞到task進(jìn)程池中執(zhí)行
    echo PHP_EOL;
    echo " Timer";
    var_dump($interval);
    echo PHP_EOL;
});





$serv->on("connect",function (swoole_server $server,  $fd,  $from_id){
// $server是swoole_server對(duì)象
// $fd是連接的文件描述符,發(fā)送數(shù)據(jù)/關(guān)閉連接時(shí)需要此參數(shù)
// $from_id來(lái)自那個(gè)Reactor線程
// $server是swoole_server對(duì)象
// $fd是連接的文件描述符,發(fā)送數(shù)據(jù)/關(guān)閉連接時(shí)需要此參數(shù)
// $from_id來(lái)自那個(gè)Reactor線程
// onConnect/onClose這2個(gè)回調(diào)發(fā)生在worker進(jìn)程內(nèi),而不是主進(jìn)程。
// UDP協(xié)議下只有onReceive事件,沒(méi)有onConnect/onClose事件
    echo PHP_EOL;
    echo " connect";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
});




//接收到數(shù)據(jù)時(shí)回調(diào)此函數(shù),發(fā)生在worker進(jìn)程中
$serv->on("Receive",function (swoole_server $server,  $fd,  $from_id,  $data){
// $server,swoole_server對(duì)象
// $fd,TCP客戶端連接的文件描述符
// $from_id,TCP連接所在的Reactor線程ID
// $data,收到的數(shù)據(jù)內(nèi)容,可能是文本或者二進(jìn)制內(nèi)容
//詳情  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數(shù)據(jù)包時(shí)回調(diào)此函數(shù),發(fā)生在worker進(jìn)程中。
$serv->on("Packet",function (swoole_server $server, string $data, array $client_info){
// $server,swoole_server對(duì)象
// $data,收到的數(shù)據(jù)內(nèi)容,可能是文本或者二進(jìn)制內(nèi)容
// $client_info,客戶端信息包括address/port/server_socket 3項(xiàng)數(shù)據(jù)
// 服務(wù)器同時(shí)監(jiān)聽(tīng)TCP/UDP端口時(shí),收到TCP協(xié)議的數(shù)據(jù)會(huì)回調(diào)onReceive,收到UDP數(shù)據(jù)包回調(diào)onPacket
    echo PHP_EOL;
    echo " Packet";
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
    var_dump($client_info);
    echo PHP_EOL;
});



//TCP客戶端連接關(guān)閉后,在worker進(jìn)程中回調(diào)此函數(shù)
$serv->on("Close",function (swoole_server $server, int $fd, int $from_id){
// $server是swoole_server對(duì)象
// $fd是連接的文件描述符
// $from_id來(lái)自那個(gè)reactor線程
// 注意:這里回調(diào)onClose時(shí)表示客戶端連接已經(jīng)關(guān)閉,所以無(wú)需執(zhí)行$server->close($fd)。代碼中執(zhí)行$serv->close($fd) 會(huì)拋出PHP錯(cuò)誤告警。
    echo PHP_EOL;
    echo " Close";
    echo PHP_EOL;
    var_dump($fd);
    echo PHP_EOL;
    var_dump($from_id);
    echo PHP_EOL;
});



//在task_worker進(jìn)程內(nèi)被調(diào)用。worker進(jìn)程可以使用swoole_server_task函數(shù)向task_worker進(jìn)程投遞新的任務(wù)
$serv->on("Task",function (swoole_server $serv, int $task_id, int $from_id, string $data){
// $task_id是任務(wù)ID,由swoole擴(kuò)展內(nèi)自動(dòng)生成,用于區(qū)分不同的任務(wù)。
//$task_id和$from_id組合起來(lái)才是全局唯一的,不同的worker進(jìn)程投遞的任務(wù)ID可能會(huì)有相同
// $from_id來(lái)自于哪個(gè)worker進(jìn)程
// $data 是任務(wù)的內(nèi)容
// 返回執(zhí)行結(jié)果到worker進(jìn)程
// 1.7.2以上的版本,在onTask函數(shù)中 return字符串,表示將此內(nèi)容返回給worker進(jìn)程。
//worker進(jìn)程中會(huì)觸發(fā)onFinish函數(shù),表示投遞的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;
});





//當(dāng)worker進(jìn)程投遞的任務(wù)在task_worker中完成時(shí),task進(jìn)程會(huì)通過(guò)swoole_server->finish()方法將任務(wù)處理的結(jié)果發(fā)送給worker進(jìn)程。
$serv->on("Finish",function (swoole_server $serv, int $task_id, string $data){
// $task_id是任務(wù)的ID
// $data是任務(wù)處理的結(jié)果內(nèi)容
// task進(jìn)程的onTask事件中沒(méi)有調(diào)用finish方法或者return結(jié)果。worker進(jìn)程不會(huì)觸發(fā)onFinish
    echo PHP_EOL;
    echo " Finish";
    echo PHP_EOL;
    var_dump($task_id);
    echo PHP_EOL;
    var_dump($data);
    echo PHP_EOL;
});



//當(dāng)工作進(jìn)程收到由sendMessage發(fā)送的管道消息時(shí)會(huì)觸發(fā)onPipeMessage事件。worker/task進(jìn)程都可能會(huì)觸發(fā)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;
});



//當(dāng)worker/task_worker進(jìn)程發(fā)生異常后會(huì)在Manager進(jìn)程內(nèi)回調(diào)此函數(shù)
$serv->on("WorkerError",function (swoole_server $serv, int $worker_id, int $worker_pid, int $exit_code){
// $worker_id是異常進(jìn)程的編號(hào)
// $worker_pid是異常進(jìn)程的ID
// $exit_code退出的狀態(tài)碼,范圍是 1 ~255
// 此函數(shù)主要用于報(bào)警和監(jiān)控,一旦發(fā)現(xiàn)Worker進(jìn)程異常退出,
// 那么很有可能是遇到了致命錯(cuò)誤或者進(jìn)程CoreDump。通過(guò)記錄日志或者發(fā)送報(bào)警的信息來(lái)提示開(kāi)發(fā)者進(jìn)行相應(yīng)的處理。
    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;
});





//當(dāng)管理進(jìn)程啟動(dòng)時(shí)調(diào)用它,函數(shù)原型:
$serv->on("ManagerStart",function (swoole_server $serv){
// 在這個(gè)回調(diào)函數(shù)中可以修改管理進(jìn)程的名稱。
// 注意manager進(jìn)程中不能添加定時(shí)器
// manager進(jìn)程中可以調(diào)用task功能
    echo PHP_EOL;
    echo " ManagerStart";
    echo PHP_EOL;
});





//當(dāng)管理進(jìn)程結(jié)束時(shí)調(diào)用它,函數(shù)原型:
$serv->on("ManagerStop",function (swoole_server $serv){
    echo PHP_EOL;
    echo " ManagerStop";
    echo PHP_EOL;
});



呼,終于寫(xiě)完了,我整理這兩個(gè)文件的目的是方便大家自己測(cè)試,官網(wǎng)有文檔,我做的只是代碼化。

當(dāng)我把這些全部看一遍之后,我對(duì)swoole_server有了大體印象,比如worker,比如task等等。
來(lái),上個(gè)圖

圖片看不到,看這里

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



下面開(kāi)始我最喜歡的環(huán)節(jié) ,跑程序

server.php

start時(shí)會(huì)失敗
$serv = new swoole_server( $host,  $port);
$serv->set(array(
     "worker_num" => 3,   //工作進(jìn)程數(shù)量
 ));
include "OnEvent.php";
$serv->start();

client.php

on("connect", function($cli) {
    $cli->send("hello world
");
});
$client->on("receive", function($cli, $data){
    echo "Received: ".$data."
";
});
$client->on("error", function($cli){
    echo "Connect failed
";
});
$client->on("close", function($cli){
    echo "Connection close
";
});
//發(fā)起網(wǎng)絡(luò)連接
$client->connect("127.0.0.1", 9501, 0.5);

我在server.php里引入了OnEvent.php(我寫(xiě)上了所有的回調(diào)函數(shù))
我想看看,server做了什么
來(lái),開(kāi)始

php server.php

運(yùn)行結(jié)果

 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)

程序并沒(méi)有死,上面的是回調(diào)函數(shù)里面的輸出
server先是 執(zhí)行start,然后按照設(shè)置的worker_num的數(shù)目創(chuàng)建worker觸發(fā)WorkerStart的回調(diào),同時(shí)創(chuàng)建Manager執(zhí)行了ManagerStart
我們?cè)倏纯瓷厦娴膬蓚€(gè)圖片,結(jié)合server的運(yùn)行結(jié)果,想必會(huì)更多一些了解
我覺(jué)得兩個(gè)圖畫(huà)的很好,讓我再看一遍。

好的,順便的,看到了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)
}

因?yàn)榕渲玫臎](méi)寫(xiě)task,并且當(dāng)前沒(méi)有客戶端連上來(lái),這里還有一些屬性沒(méi)有展示出來(lái)
大家詳細(xì)的看這里 屬性列表

好的,讓我們運(yùn)行客戶端

php client.php




 connect
int(1) //  這個(gè)是 fd

int(0)// 這個(gè)是 from_id


 Receive
int(1)//  這個(gè)是 fd

int(0)// 這個(gè)是 from_id

string(12) "hello world
"http:// 這個(gè)是 data

這里貼出來(lái) server端多出來(lái)的內(nèi)容

補(bǔ)充一下:對(duì)一個(gè)對(duì)象使用get_class_methods可以獲得對(duì)象的所有方法,今天忘了怎么獲取客戶端ip地址了,用這個(gè)查了一下,是server的connection_info方法

好的,希望大家用多測(cè)試測(cè)試,觀察server的變化,體會(huì)swoole的server調(diào)用
結(jié)合運(yùn)行結(jié)果來(lái)看流程圖

今天暫時(shí)到這里,哪里我說(shuō)的不對(duì),請(qǐng)大家指正,我也是一個(gè)學(xué)習(xí)中的人

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.specialneedsforspecialkids.com/yun/21078.html

相關(guān)文章

  • 一個(gè)簡(jiǎn)單混合協(xié)議通訊列子,物聯(lián)網(wǎng)和互聯(lián)網(wǎng)通訊

    摘要:初始化發(fā)送消息判斷用戶是否登錄如果沒(méi)有登錄拒絕連接斷開(kāi)清除信息處理協(xié)議主要是方法,輪訓(xùn)獲取消息。 這個(gè)列子主要討論Tcp,WebSocket和http之間的通訊。長(zhǎng)連接和長(zhǎng)連接通訊,長(zhǎng)連接和短連接通訊。其他協(xié)議同理可得 Tcp: 代表硬件設(shè)備 WebSocket: 代表客戶端 http: 代表網(wǎng)頁(yè) 本列子是基于one框架 (https://github.com/lizhicha...

    王軍 評(píng)論0 收藏0
  • php使用swoole應(yīng)用場(chǎng)景

    摘要:?jiǎn)芜M(jìn)程讀寫(xiě)性能可達(dá)萬(wàn),不同的進(jìn)程使用不同的管道通信,可以最大化利用多核。但這任務(wù)如果是調(diào)用程序接口時(shí),由于網(wǎng)絡(luò)的延遲,增加的任務(wù)大于消費(fèi)的任務(wù)時(shí),內(nèi)存占用會(huì)不斷的增加,導(dǎo)致服務(wù)器的內(nèi)存被占滿。 應(yīng)用場(chǎng)景簡(jiǎn)介 與硬件設(shè)備連接通訊(定位設(shè)備) IM系統(tǒng)(用于直播頁(yè)面的聊天通訊) 場(chǎng)景1 - 實(shí)時(shí)收集定位數(shù)據(jù)實(shí)時(shí)輸出(例 滴滴司機(jī)行駛軌跡) 說(shuō)明:需要將所有的定位設(shè)備實(shí)時(shí)的接收,將實(shí)時(shí)的...

    jsliang 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<