成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專(zhuān)欄INFORMATION COLUMN

Swoole筆記(一)

SHERlocked93 / 510人閱讀

摘要:修復(fù)添加超過(guò)萬(wàn)個(gè)以上定時(shí)器時(shí)發(fā)生崩潰的問(wèn)題增加模塊,下高性能序列化庫(kù)修復(fù)監(jiān)聽(tīng)端口設(shè)置無(wú)效的問(wèn)題等。線程來(lái)處理網(wǎng)絡(luò)事件輪詢,讀取數(shù)據(jù)。當(dāng)?shù)娜挝帐殖晒α艘院?,由這個(gè)線程將連接成功的消息告訴進(jìn)程,再由進(jìn)程轉(zhuǎn)交給進(jìn)程。此時(shí)進(jìn)程觸發(fā)事件。

本文示例代碼詳見(jiàn):https://github.com/52fhy/swoo...。

簡(jiǎn)介

Swoole是一個(gè)PHP擴(kuò)展,提供了PHP語(yǔ)言的異步多線程服務(wù)器,異步TCP/UDP網(wǎng)絡(luò)客戶端,異步MySQL,異步Redis,數(shù)據(jù)庫(kù)連接池,AsyncTask,消息隊(duì)列,毫秒定時(shí)器,異步文件讀寫(xiě),異步DNS查詢。 Swoole內(nèi)置了Http/WebSocket服務(wù)器端/客戶端、Http2.0服務(wù)器端。

Swoole: PHP的異步、并行、高性能網(wǎng)絡(luò)通信引擎
http://www.swoole.com/

Github:
https://github.com/swoole
https://github.com/matyhtf

安裝

Swoole需要使用源碼安裝。暫無(wú)Windows版擴(kuò)展。

源碼安裝
wget -O swoole.zip https://github.com/swoole/swoole-src/archive/v1.9.11.zip
unzip swoole.zip
cd swoole
phpize
./configure
make && make install
pecl安裝

由于pecl是需要編譯的,所以需要先安裝編譯器(已安裝編譯器可以忽略):

yum install -y gcc gcc-c++ make cmake bison autoconf

然后:

pecl install swoole
pecl install redis

pecl安裝擴(kuò)展完成后會(huì)提示添加so文件到php.ini。示例:

Build process completed successfully
Installing "/usr/lib64/php/modules/swoole.so"
install ok: channel://pecl.php.net/swoole-1.9.11
configuration option "php_ini" is not set to php.ini location
You should add "extension=swoole.so" to php.ini

添加示例:

[swoole]
extension = /usr/lib64/php/modules/swoole.so
版本選擇

建議使用的版本(截止時(shí)間2017-6-3)

穩(wěn)定版:v1.9.9
預(yù)覽版:v2.0.7
1.9.x 分支已進(jìn)入特性鎖定期,不再開(kāi)發(fā)新功能,僅修復(fù)BUG。

最低版本:
建議1.8.6+。PHP7建議使用1.9.2+

建議使用的PHP版本

PHP5.5或更高版本
PHP7.0.13或更高版本
使用TP3.1+框架的朋友升級(jí)到PHP7.1.0可能會(huì)出現(xiàn)rewrite失效問(wèn)題。建議PHP7.0.x系列。

快速查看當(dāng)前swoole的版本:

php --ri swoole

1.8.6~1.8.13 都是小范圍BUG修復(fù)及功能新增。其中 1.8.11 增加SIGRTMIN信號(hào)處理函數(shù),用于重新打開(kāi)日志文件。

1.8.6 版本是一個(gè)重要的BUG修復(fù)版本,主要修復(fù)了PHP7環(huán)境下HttpServer、TCPClient、HttpClient、Redis等客戶端存在的內(nèi)存泄漏、崩潰問(wèn)題。

1.9.0 版本增加了多項(xiàng)新特性,修復(fù)了多個(gè)已知問(wèn)題。1.9版本是100%向下兼容1.8的,用戶可無(wú)縫升級(jí)。

1.9.1 修復(fù)PHP7下啟用opcache導(dǎo)致崩潰的問(wèn)題;重構(gòu)reopen log file特性,收到SIGRTMIN信號(hào)后重新打開(kāi)日志文件并重定向標(biāo)準(zhǔn)輸出 等。

1.9.2 修復(fù)PHP7下發(fā)生zend_mm_heap corrupted的問(wèn)題 等。

1.9.4 修復(fù)WebSocket服務(wù)器默認(rèn)onRequest方法內(nèi)存泄漏問(wèn)題 等。

1.9.5 增加pid_file選項(xiàng),在Server啟動(dòng)時(shí)將主進(jìn)程ID寫(xiě)入指定的文件 等。

1.9.6 修復(fù)添加超過(guò)1萬(wàn)個(gè)以上定時(shí)器時(shí)發(fā)生崩潰的問(wèn)題;增加swoole_serialize模塊,PHP7下高性能序列化庫(kù);修復(fù)監(jiān)聽(tīng)UDP端口設(shè)置onPacket無(wú)效的問(wèn)題 等。

1.9.9 修復(fù)Http2客戶端POST數(shù)據(jù)時(shí)協(xié)議錯(cuò)誤問(wèn)題 等。

1.9.11 修復(fù)WebSocket服務(wù)器onOpen回調(diào)函數(shù)存在內(nèi)存泄漏的問(wèn)題;修復(fù)Http服務(wù)器文件上傳在5.6版本發(fā)生崩潰的問(wèn)題;優(yōu)化添加Task和Timer的定時(shí)器性能,提升分支預(yù)測(cè)成功率 等。

Swoole的進(jìn)程模型 運(yùn)行模式

Swoole目前總共有三種運(yùn)行模式,默認(rèn)為多進(jìn)程模式(SWOOLE_PROCESS)。

# Base模式(SWOOLE_BASE)
傳統(tǒng)的異步非阻塞Server,reactor和worker是同一個(gè)角色。TCP連接是在worker進(jìn)程中維持的。
如果客戶端連接之間不需要交互,可以使用BASE模式。如Memcache、Http服務(wù)器等。

# 線程模式
多線程Worker模式,Reactor線程來(lái)處理網(wǎng)絡(luò)事件輪詢,讀取數(shù)據(jù)。得到的請(qǐng)求交給Worker線程去處理。

缺點(diǎn):一個(gè)線程發(fā)生內(nèi)存錯(cuò)誤,整個(gè)進(jìn)程會(huì)全部結(jié)束。
由于PHP的ZendVM在多線程模式存在內(nèi)存錯(cuò)誤,多線程模式在v1.6.0版本后已關(guān)閉。

# 進(jìn)程模式
與多線程Worker模式不同的是,線程換成了進(jìn)程。Reactor線程來(lái)處理網(wǎng)絡(luò)事件輪詢,讀取數(shù)據(jù)。得到的請(qǐng)求交給Worker進(jìn)程去處理。適合業(yè)務(wù)邏輯非常復(fù)雜的場(chǎng)景。如WebSocket服務(wù)器等。
$serv = new swoole_server(string $host, int $port, int $mode = SWOOLE_PROCESS, int $sock_type = SWOOLE_SOCK_TCP);
實(shí)例分析

我們來(lái)使用實(shí)例進(jìn)行分析:

on("connect", function ($serv, $fd){ });
$server->on("receive", function ($serv, $fd, $from_id, $data){ });
$server->on("close", function ($serv, $fd){ });

$server -> start();

繼續(xù)在Shell中輸入以下命令:

php swoole_tcp_server.php
pstree -ap|grep swoole_tcp_server
  |   |       `-php,2454 swoole_tcp_server.php
  |   |           |-php,2456 swoole_tcp_server.php
  |   |           |   `-php,2458 swoole_tcp_server.php

從系統(tǒng)的輸出中,我們可以很容看出server其實(shí)有3個(gè)進(jìn)程,進(jìn)程的pid分別是2454、2456、2458,其中2454是2456的父進(jìn)程,而2456又是2458的父進(jìn)程。

所以,其實(shí)我們雖然看起來(lái)只是啟動(dòng)了一個(gè)Server,其實(shí)最后產(chǎn)生的是三個(gè)進(jìn)程。

這三個(gè)進(jìn)程中,所有進(jìn)程的根進(jìn)程(2454),就是所謂的Master進(jìn)程;而2456進(jìn)程,則是Manager進(jìn)程;最后的2458進(jìn)程,是Worker進(jìn)程。

基于此,我們簡(jiǎn)單梳理一下,當(dāng)執(zhí)行的start方法之后,發(fā)生了什么:

守護(hù)進(jìn)程模式下,當(dāng)前進(jìn)程fork出Master進(jìn)程,然后退出,Master進(jìn)程觸發(fā)OnMasterStart事件。

Master進(jìn)程啟動(dòng)成功之后,fork出Manager進(jìn)程,并觸發(fā)OnManagerStart事件。

Manager進(jìn)程啟動(dòng)成功時(shí)候,fork出Worker進(jìn)程,并觸發(fā)OnWorkerStart事件。

非守護(hù)進(jìn)程模式下,則當(dāng)前進(jìn)程直接作為Master進(jìn)程工作。

所以,一個(gè)最基礎(chǔ)的Swoole Server,至少需要有3個(gè)進(jìn)程,分別是Master進(jìn)程、Manager進(jìn)程和Worker進(jìn)程。

事實(shí)上,一個(gè)多進(jìn)程模式下的Swoole Server中,有且只有一個(gè)Master進(jìn)程;有且只有一個(gè)Manager進(jìn)程;卻可以有n個(gè)Worker進(jìn)程。

進(jìn)程模型

Master進(jìn)程是一個(gè)多線程進(jìn)程,其中有一組非常重要的線程,叫做Reactor線程(組),每當(dāng)一個(gè)客戶端連接上服務(wù)器的時(shí)候,都會(huì)由Master進(jìn)程從已有的Reactor線程中,根據(jù)一定規(guī)則挑選一個(gè),專(zhuān)門(mén)負(fù)責(zé)向這個(gè)客戶端提供維持鏈接、處理網(wǎng)絡(luò)IO與收發(fā)數(shù)據(jù)等服務(wù)。分包拆包等功能也是在這里完成。

Manager進(jìn)程,某種意義上可以看做一個(gè)代理層,它本身并不直接處理業(yè)務(wù),其主要工作是將Master進(jìn)程中收到的數(shù)據(jù)轉(zhuǎn)交給Worker進(jìn)程,或者將Worker進(jìn)程中希望發(fā)給客戶端的數(shù)據(jù)轉(zhuǎn)交給Master進(jìn)程進(jìn)行發(fā)送。

Manager進(jìn)程還負(fù)責(zé)監(jiān)控Worker進(jìn)程,如果Worker進(jìn)程因?yàn)槟承┮馔鈷炝?,Manager進(jìn)程會(huì)重新拉起新的Worker進(jìn)程,有點(diǎn)像Supervisor的工作。而這個(gè)特性,也是最終實(shí)現(xiàn)熱重載的核心機(jī)制。

Worker進(jìn)程其實(shí)就是處理各種業(yè)務(wù)工作的進(jìn)程,Manager將數(shù)據(jù)包轉(zhuǎn)交給Worker進(jìn)程,然后Worker進(jìn)程進(jìn)行具體的處理,并根據(jù)實(shí)際情況將結(jié)果反饋給客戶端。

我們可以總結(jié)出來(lái)上面簡(jiǎn)單的Server,當(dāng)客戶端連接的時(shí)候這個(gè)過(guò)程中,三種進(jìn)程之間是怎么協(xié)作的:

Client主動(dòng)Connect的時(shí)候,Client實(shí)際上是與Master進(jìn)程中的某個(gè)Reactor線程發(fā)生了連接。

當(dāng)TCP的三次握手成功了以后,由這個(gè)Reactor線程將連接成功的消息告訴Manager進(jìn)程,再由Manager進(jìn)程轉(zhuǎn)交給Worker進(jìn)程。

在這個(gè)Worker進(jìn)程中觸發(fā)了OnConnect的方法。

當(dāng)Client向Server發(fā)送了一個(gè)數(shù)據(jù)包的時(shí)候,首先收到數(shù)據(jù)包的是Reactor線程,同時(shí)Reactor線程會(huì)完成組包,再將組好的包交給Manager進(jìn)程,由Manager進(jìn)程轉(zhuǎn)交給Worker。

此時(shí)Worker進(jìn)程觸發(fā)OnReceive事件。

如果在Worker進(jìn)程中做了什么處理,然后再用Send方法將數(shù)據(jù)發(fā)回給客戶端時(shí),數(shù)據(jù)則會(huì)沿著這個(gè)路徑逆流而上。

Swoole進(jìn)程/線程結(jié)構(gòu)圖:

現(xiàn)在,我們基于上面的例子修改代碼,來(lái)看看一個(gè)簡(jiǎn)單的多進(jìn)程Swoole Server的幾個(gè)基本配置:

set(array(
    "demonize" => false,//是否后臺(tái)運(yùn)行
    "reactor_num" => 2,
    "worker_num" => 4
));

$server -> start();

reactor_num:表示Master進(jìn)程中,Reactor線程總共開(kāi)多少個(gè),注意,這個(gè)可不是越多越好,因?yàn)橛?jì)算機(jī)的CPU是有限的,所以一般設(shè)置為與CPU核心數(shù)量相同,或者兩倍即可。

worker_num:表示啟動(dòng)多少個(gè)Worker進(jìn)程,同樣,Worker進(jìn)程數(shù)量不是越多越好,仍然設(shè)置為與CPU核心數(shù)量相同,或者兩倍即可。

我們可以在Shell里運(yùn)行,使用pstree查看進(jìn)程模型結(jié)構(gòu):

php swoole_tcp_server.php
pstree -ap|grep swoole_tcp
  |   |       `-php,2505 swoole_tcp_server.php
  |   |           |-php,2507 swoole_tcp_server.php
  |   |           |   |-php,2510 swoole_tcp_server.php
  |   |           |   |-php,2511 swoole_tcp_server.php
  |   |           |   |-php,2512 swoole_tcp_server.php
  |   |           |   `-php,2513 swoole_tcp_server.php
回調(diào)函數(shù)

Swoole作為Server時(shí),回調(diào)函數(shù)有很多。但可以簡(jiǎn)單分個(gè)類(lèi):
1) 進(jìn)程啟動(dòng)時(shí)執(zhí)行的:onStart、onManagerStart、onWorkerStart;onWorkerStop、onManagerStop、onShutdown;onWorkerError
2) 客戶端交互時(shí)觸發(fā)的:onReceive/onRequest/onPacket/onMessage、onOpen/onConnect、onClose
3) Task:onTask、onFinish
4) Timer:onTimer

事件執(zhí)行順序:

所有事件回調(diào)均在$server->start后發(fā)生

服務(wù)器關(guān)閉程序終止時(shí)最后一次事件是onShutdown

服務(wù)器啟動(dòng)成功后,onStart/onManagerStart/onWorkerStart會(huì)在不同的進(jìn)程內(nèi)并發(fā)執(zhí)行。

onReceive/onConnect/onClose/onTimer在worker進(jìn)程(包括task進(jìn)程)中各自觸發(fā)

worker/task進(jìn)程啟動(dòng)/結(jié)束時(shí)會(huì)分別調(diào)用onWorkerStart/onWorkerStop

onTask事件僅在task進(jìn)程中發(fā)生

onFinish事件僅在worker進(jìn)程中發(fā)生

onStart/onManagerStart/onWorkerStart 3個(gè)事件的執(zhí)行順序是不確定的

UDP協(xié)議下只有onReceive事件,沒(méi)有onConnect/onClose事件

如果未設(shè)置onPacket回調(diào)函數(shù),收到UDP數(shù)據(jù)包默認(rèn)會(huì)回調(diào)onReceive函數(shù)

onOpen事件回調(diào)是可選的:當(dāng)WebSocket客戶端與服務(wù)器建立連接并完成握手后會(huì)回調(diào)此函數(shù)

實(shí)際使用的時(shí)候不是所有回調(diào)都可以使用的,例如UDP服務(wù)器沒(méi)有onConnect/onClose;例如接收數(shù)據(jù),在WebSocket里使用onReceive,在HttpServer使用onRequest,在UDPServer使用onPacket。

示例:

set(array(
    "daemonize" => false,
    "reactor_num" => 2,
    "worker_num" => 4
));

$server->on("connect", function ($serv, $fd){ 
    echo "client connect. fd is {$fd}
";
});

$server->on("receive", function ($serv, $fd, $from_id, $data){
    echo "client connect. fd is {$fd}
";
});

$server->on("close", function ($serv, $fd){
    echo "client close. fd is {$fd}
";
});

// 以下回調(diào)發(fā)生在Master進(jìn)程
$server->on("start", function (swoole_server $server){
    echo "On master start.
";
});
$server->on("shutdown", function (swoole_server $server){
    echo "On master shutdown.
";
});

// 以下回調(diào)發(fā)生在Manager進(jìn)程
$server->on("ManagerStart", function (swoole_server $server){
    echo "On manager start.
";
});
$server->on("ManagerStop", function (swoole_server $server){
    echo "On manager stop.
";
});

// 以下回調(diào)也發(fā)生在Worker進(jìn)程
$server->on("WorkerStart", function (swoole_server $server, $worker_id){
    echo "Worker start
";
});
$server->on("WorkerStop", function(swoole_server $server, $worker_id){
    echo "Worker stop
";
});
$server->on("WorkerError", function(swoole_server $server, $worker_id, $worker_pid, $exit_code){
    echo "Worker error
";
});

$server -> start();
編程須知

不要在代碼中執(zhí)行sleep以及其他睡眠函數(shù),這樣會(huì)導(dǎo)致整個(gè)進(jìn)程阻塞

exit/die是危險(xiǎn)的,會(huì)導(dǎo)致worker進(jìn)程退出

可通過(guò)register_shutdown_function來(lái)捕獲致命錯(cuò)誤,在進(jìn)程異常退出時(shí)做一些請(qǐng)求工作,具體參看/wiki/page/305.html

PHP代碼中如果有異常拋出,必須在回調(diào)函數(shù)中進(jìn)行try/catch捕獲異常,否則會(huì)導(dǎo)致工作進(jìn)程退出

swoole不支持set_exception_handler,必須使用try/catch方式處理異常

Worker進(jìn)程不得共用同一個(gè)RedisMySQL等網(wǎng)絡(luò)服務(wù)客戶端,Redis/MySQL創(chuàng)建連接的相關(guān)代碼可以放到onWorkerStart回調(diào)函數(shù)中。原因是如果共用1個(gè)連接,那么返回的結(jié)果無(wú)法保證被哪個(gè)進(jìn)程處理。持有連接的進(jìn)程理論上都可以對(duì)這個(gè)連接進(jìn)行讀寫(xiě),這樣數(shù)據(jù)就發(fā)生錯(cuò)亂了。具體參考/wiki/page/325.html

不能使用類(lèi)的屬性保存客戶端連接信息,因?yàn)橐粋€(gè)worker進(jìn)程可以處理多個(gè)客戶端連接,導(dǎo)致類(lèi)屬性數(shù)據(jù)錯(cuò)亂。常量則是可以的。

歡迎關(guān)注公眾號(hào)及時(shí)獲取最新文章推送!


推薦!每月僅需$2.5,即可擁有配置SSD的VPS!

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

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/23065.html

相關(guān)文章

  • swoole 學(xué)習(xí)筆記swoole 真的優(yōu)秀個(gè)框架

    摘要:所以,我感覺(jué)學(xué)習(xí),需要一個(gè)引導(dǎo)。學(xué)習(xí)參考鏈接喵星球特別厲害的一個(gè)官網(wǎng)的幾個(gè)框架文檔優(yōu)勢(shì)先看一下的結(jié)構(gòu)設(shè)計(jì)的應(yīng)用場(chǎng)景的設(shè)計(jì)項(xiàng)目中引入一個(gè)簡(jiǎn)易的具體參考一篇文章,集合和的簡(jiǎn)易實(shí)例項(xiàng)目中引入結(jié)合致敬 前期學(xué)完了操作系統(tǒng),特別是知道了進(jìn)程,線程 調(diào)度的問(wèn)題?;貋?lái)看,發(fā)現(xiàn)了很多細(xì)節(jié)。第三次看文檔,最初經(jīng)一個(gè)高手朋友的介紹,看swoole,說(shuō)文檔寫(xiě)的賊好。但是看的時(shí)候,也是很一頭霧水,只知道把de...

    13651657101 評(píng)論0 收藏0
  • PHP多進(jìn)程系列筆記(五)

    摘要:消息隊(duì)列更常見(jiàn)的用途是主進(jìn)程分配任務(wù),子進(jìn)程消費(fèi)執(zhí)行。子進(jìn)程前面加了個(gè),這是為了防止父進(jìn)程還未往消息隊(duì)列中加入內(nèi)容直接退出。 前面幾節(jié)都是講解pcntl擴(kuò)展實(shí)現(xiàn)的多進(jìn)程程序。本節(jié)給大家介紹swoole擴(kuò)展的swoole_process模塊。 swoole多進(jìn)程 swoole_process 是swoole提供的進(jìn)程管理模塊,用來(lái)替代PHP的pcntl擴(kuò)展。 首先,確保安裝的swoole...

    qianfeng 評(píng)論0 收藏0
  • swoole 學(xué)習(xí)筆記

    摘要:安裝準(zhǔn)備或更高版本或更高版本安裝擴(kuò)展配置支持編輯在其中加入擴(kuò)展支持服務(wù)端代碼服務(wù)端客戶端代碼測(cè)試代碼在命令模式下輸入重新再開(kāi)一個(gè)窗口可以用檢測(cè)如服務(wù)端客戶端如上,表示服務(wù)端啟動(dòng),客戶端連接服務(wù)端返回消息,一個(gè)閉環(huán)形成開(kāi)發(fā)者頭條 1.安裝準(zhǔn)備 php-5.3.10 // 或更高版本 gcc-4.4 //或更高版本 make autoconf 2.安裝swoole擴(kuò)展 w...

    justCoding 評(píng)論0 收藏0
  • Swoole筆記(二)

    摘要:配置了參數(shù)后將會(huì)啟用功能,務(wù)必要注冊(cè)個(gè)事件回調(diào)函數(shù)。周期性定時(shí)器一次性定時(shí)器清除定時(shí)器定時(shí)器回調(diào)函數(shù)注意最大不得超過(guò)。進(jìn)程中不能添加定時(shí)器。建議在回調(diào)里寫(xiě)定時(shí)器。定時(shí)器示例防止重復(fù)每隔觸發(fā)一次后執(zhí)行此函數(shù) 本文示例代碼詳見(jiàn):https://github.com/52fhy/swoo...。 重新打開(kāi)日志 在1.8.11及之后版本支持重新打開(kāi)日志:向Server主進(jìn)程發(fā)送SIGRTMIN...

    jsummer 評(píng)論0 收藏0
  • Swoole筆記(五)

    摘要:超過(guò)此數(shù)量后,新進(jìn)入的連接將被拒絕。表示連接最大允許空閑的時(shí)間。當(dāng)出錯(cuò)時(shí)底層會(huì)認(rèn)為是惡意連接,丟棄數(shù)據(jù)并強(qiáng)制關(guān)閉連接。在啟動(dòng)時(shí)自動(dòng)將進(jìn)程的寫(xiě)入到文件,在關(guān)閉時(shí)自動(dòng)刪除文件。 配置說(shuō)明 $server->set(array( daemonize => true, log_file => /www/log/swoole.log, reactor_num => 2, ...

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

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

0條評(píng)論

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