91版本福利群_精品国产丝袜自在线拍国_诱人的女老板HD在线观看_国产一卡2卡3卡4卡高清_亚洲AV无码国产精品色无友情

分享縮略圖
首頁(yè) 資訊 企業(yè) 供應(yīng)商 熱門產(chǎn)品 供求信息 閥門品牌 產(chǎn)品分類 企業(yè)展示 關(guān)注

當(dāng)前速看:Swoole - webSocket消息服務(wù)系統(tǒng)代碼設(shè)計(jì)篇

發(fā)布時(shí)間:2023-03-06 04:07:16  |  來(lái)源:騰訊云  |  

概述

已經(jīng)Swoole系列的第二篇知識(shí)點(diǎn)了,前一篇主要的針對(duì)處理的是方案設(shè)計(jì),這一篇主要是代碼實(shí)現(xiàn)的內(nèi)容,主要介紹高性能的原因已經(jīng)實(shí)現(xiàn),編程框架使用EasySwoole。


(資料圖)

Swoole 與 EasySwoole

Swoole屬于php中的一個(gè)超級(jí)擴(kuò)展,它會(huì)接管PHP的進(jìn)程,管理和分配worker,但他依賴 PHP-Cli模式。Swoole和Yaf有相似的地方,它們都是以守護(hù)進(jìn)程的模式、常駐內(nèi)存的方式達(dá)到提高處理性能。

Swoole內(nèi)置了TCP、UDP、WebSocket、協(xié)程、異步、Redis/Mysql鏈接池等高效開(kāi)發(fā)手段和方法,當(dāng)然對(duì)于新模式也有新的挑戰(zhàn),比如swoole不能使用die,會(huì)致使worker滑落,協(xié)程使用后要注意使用回調(diào)的過(guò)程,如果對(duì)php的基礎(chǔ)知識(shí)不了解的同學(xué),可以翻看我之前的php博客里的總結(jié),這里就不過(guò)多敘述了。

EasySwoole是一款非常簡(jiǎn)單上手易操作的Swoole框架,上線2年多以來(lái)經(jīng)得住生產(chǎn)環(huán)境的考驗(yàn),官網(wǎng)文檔寫的也很詳細(xì),還有專門解答的QQ群,大佬們會(huì)解答很多問(wèn)題。

安裝EasySwoole框架

之前我使用composer進(jìn)行安裝的(composer是php中管理依賴包的工具,和node里面的npm,python的pip 一樣),現(xiàn)在都使用docker鏡像直接操作了。

docker pull easyswoole/easyswoole3docker run -ti -p 9501:9501 -p 80:80 --name easyswoole easyswoole/easyswoole3 

項(xiàng)目目錄結(jié)構(gòu):

.├── App│ ├── Conf│ ├── Crontab│ ├── HttpController│ │ ├── Api│ │ └── Router.php│ ├── Log│ │ └── LogHandel.php│ ├── Models│ │ ├── ImChatModel.php│ │ ├── ImModel.php│ │ └── PushMsgModel.php│ ├── Parser│ │ └── WebSocketParser.php│ ├── Server│ │ ├── ChangPeiServer│ │ ├── MysqlServer│ │ ├── RedisServer│ │ ├── Server.php│ │ └── WebSocketServer│ ├── Utility│ │ ├── Http│ │ ├── Mall│ │ └── Ws│ ├── WebSocketController│ │ ├── Base.php│ │ ├── Error│ │ ├── V1│ ├── WebSocketEvent.php│ └── WebSocketRoute│     └── ForwardRoute.php├── EasySwooleEvent.php├── Log│ └── swoole.log

注冊(cè)服務(wù) 與啟動(dòng)加載

1.在EasySwooleEvent.php文件中加載初始化需要的Mysql、redis配置文件,所有需要的服務(wù)都需要在啟動(dòng)文件中進(jìn)行注冊(cè),才能使用。

public static function loadConf(){    $ConfPath = EASYSWOOLE_ROOT . "/App/Conf/";    $Conf  = Config::getInstance();    $files = File::scanDirectory($ConfPath);    if (!is_array($files["files"])) {        return;    }    foreach ($files["files"] as $file) {        $data = require_once $file;        $Conf->setConf(strtolower(basename($file, ".php")), (array)$data);    }}

2.注冊(cè)Mysql連接池,Mysql連接池主要設(shè)置參數(shù),

 [        "host" => "59.110.162.133",        "port" => "3306",        "database" => "swoole_msg", //cpwxw2_db_v2        "username" => "work",        "password" => "cp2018csq123456",        "timeout" => 300,        "charset" => "utf8mb4"    ],    //Mysql連接池配置    "conn_pool" => [        "timeOut" => "3.0",    //設(shè)置獲取連接池對(duì)象超時(shí)時(shí)間        "checkOut" => 30 * 1000,  //設(shè)置檢測(cè)連接存活執(zhí)行回收和創(chuàng)建的周期        "maxidleTime" => 15,       //連接池對(duì)象最大閑置時(shí)間(秒)        "maxObjectNumber" => 100,       //設(shè)置最大連接池存在連接對(duì)象數(shù)量        "minObjectNumber" => 5,        //設(shè)置最小連接池存在連接對(duì)象數(shù)量        "autoPing" => 5,        //設(shè)置自動(dòng)ping客戶端鏈接的間隔    ],];

3.注冊(cè)redis鏈接池

use \EasySwoole\Redis\Config\RedisConfig;use \EasySwoole\RedisPool\RedisPool;$redisConf = GlobalConfig::getInstance()->getConf("redis");RedisPool::getInstance()->register(new RedisConfig($redisConf),"redis");

4.注冊(cè)自定義log

use  \EasySwoole\EasySwoole\Logger;Logger::getInstance(new \App\Log\LogHandel());

5.我的項(xiàng)目里還使用了crontab模塊

use Swoole\Coroutine\Scheduler;use EasySwoole\EasySwoole\Crontab\Crontab;//用戶通知隊(duì)列Crontab::getInstance()->addTask(\App\Crontab\PushUserNoticeMsg::class);

6.添加熱啟動(dòng)

Swoole的服務(wù)屬于常駐內(nèi)存加載類型的服務(wù),所以每次修改代碼后都需要重啟服務(wù),所以為了方便,添加了熱加載目錄,熱加載原理就是當(dāng)檢測(cè)到指定目錄有代碼更新時(shí),用傳遞信號(hào)的方式進(jìn)行,指揮進(jìn)程進(jìn)行重新加載。

$hotReloadOptions = new \EasySwoole\HotReload\HotReloadOptions;$hotReload = new \EasySwoole\HotReload\HotReload($hotReloadOptions);$hotReloadOptions->setMonitorFolder([EASYSWOOLE_ROOT . "/App"]);$server = ServerManager::getInstance()->getSwooleServer();$hotReload->attachToServer($server);

7.啟動(dòng)/停止服務(wù),參數(shù)說(shuō)明

-mode 說(shuō)明啟動(dòng)服務(wù)類型

-d 以守護(hù)進(jìn)程的方式

php easyswoole server start -mode=websocket -dphp easyswoole server stop 

異步和 DB(Redis/Mysql)使用

1.高性能的異步操作

如果是不依賴于結(jié)果的計(jì)算,異步操作提高性能的有效手段之一,異步操作不需要等待結(jié)果,更好的利用CPU和I/O傳輸。

use EasySwoole\EasySwoole\Task\TaskManager;TaskManager::getInstance()->async(function () use ($tableName,$data) {    // todo code ...});

2.Redis/Mysql使用

在高并發(fā)情況下,資源浪費(fèi)的占用時(shí)間越短越好,可以提高程序的服務(wù)效率。在ORM默認(rèn)情況下是使用defer方法獲取pool內(nèi)的連接資源,并在協(xié)程退出時(shí)自動(dòng)歸還,在此情況下,在帶來(lái)便利的同時(shí),會(huì)造成不必要資源的浪費(fèi)。

我們可以使用invoke方式,讓ORM查詢結(jié)束后馬上歸還資源,可以提高資源的利用率。

Mysql的使用Demo.

DbManager::getInstance()->invoke(function (ClientInterface $client)use ($where, $tableName, $count) {    $pushMsgModel = PushMsgModel::invoke($client);    $pushMsgObj = $pushMsgModel->tableName($tableName)        ->field(["push_id"])        ->get($where);}, self::MYSQL_CONN_NAME);

Redis的使用Demo.

## invoke方式public function setAuthorFd(int $uid, int $fd){    RedisPool::invoke(function (Redis $redis) use ($fd, $uid) {        $sRet = $redis->zAdd(self::PUSH_MSG_AUTHOR_NOTICE_SYSTEM, $uid, $fd);    }, self::REDIS_CONN_NAME);}## defer方式$redis = \EasySwoole\RedisPool\RedisPool::defer("redis");$data = $redis->lRange(self::PUSH_MSG_COMMENT_DELAY_LISTS, 0, 1000);

WebSocket服務(wù)

1.WebSocket協(xié)議是什么

WebSocket協(xié)議是基于TCP的一種新的網(wǎng)絡(luò)協(xié)議。它實(shí)現(xiàn)了瀏覽器與服務(wù)器全雙工(full-duplex)通信——允許服務(wù)器主動(dòng)發(fā)送信息給客戶端。

在沒(méi)有WebSocket協(xié)議之前,在網(wǎng)頁(yè)中,實(shí)現(xiàn)一個(gè)聊天室只能使用ajax 不斷輪詢,請(qǐng)求服務(wù)器是否有數(shù)據(jù)產(chǎn)生,而這樣的實(shí)現(xiàn)方法會(huì)出現(xiàn)一系列的問(wèn)題:

如果輪詢時(shí)間間隔太短,會(huì)導(dǎo)致客戶端和服務(wù)端在一個(gè)時(shí)間段內(nèi)不斷的進(jìn)行http tcp的握手/揮手動(dòng)作和http 請(qǐng)求頭,響應(yīng)頭的傳輸,大量消耗服務(wù)器資源,如果用戶量大的情況,會(huì)造成服務(wù)器的繁忙以至于宕機(jī)客戶端每次只能通過(guò)發(fā)送http 請(qǐng)求獲得服務(wù)器是否有數(shù)據(jù)返回,且數(shù)據(jù)的及時(shí)性無(wú)法保證

正因?yàn)樵谶@種情況下,所以WebSocket出現(xiàn)了,它只需要一次http握手,就可以保持一個(gè)長(zhǎng)連接,使得服務(wù)器可以主動(dòng)發(fā)送消息給客戶端,大大減少了輪詢機(jī)制的消耗。

2.WebSocket協(xié)議實(shí)現(xiàn)原理

在實(shí)現(xiàn)websocket連線過(guò)程中,需要通過(guò)瀏覽器發(fā)出websocket連線請(qǐng)求,然后服務(wù)器發(fā)出回應(yīng),這個(gè)過(guò)程通常稱為握手 。

在 WebSocket API,瀏覽器和服務(wù)器只需要做一個(gè)握手的動(dòng)作,然后,瀏覽器和服務(wù)器之間就形成了一條快速通道。兩者之間就直接可以數(shù)據(jù)互相傳送。在此WebSocket 協(xié)議中,為我們實(shí)現(xiàn)即時(shí)服務(wù)帶來(lái)了兩大好處:

Header: 互相溝通的Header是很小的-大概只有 2 BytesServer Push: 服務(wù)器的推送,服務(wù)器不再被動(dòng)的接收到瀏覽器的請(qǐng)求之后才返回?cái)?shù)據(jù),而是在有新數(shù)據(jù)時(shí)就主動(dòng)推送給瀏覽器。
//$fd,指的是系統(tǒng)里的文件描述符fduse EasySwoole\EasySwoole\ServerManager;$server = ServerManager::getInstance()->getSwooleServer();$server->push($fd,json_encode($messageData));//獲取當(dāng)前鏈接的詳細(xì)信息$info = $server->getClientInfo($fd);//獲取全部websocket中的鏈接fd//全員在線消息通知$server = ServerManager::getInstance()->getSwooleServer();$start_fd = 0;while(true){    $conn_list = $server->getClientList( $start_fd, $this->limit );    if ($conn_list===false || count($conn_list) === 0 || empty($conn_list))    {        break;    }    $start_fd = end($conn_list);    foreach ($conn_list as $fd){        $info = $server->getClientInfo($fd);        if ($info && $info["websocket_status"] === WEBSOCKET_STATUS_FRAME) {            $server->push($fd, json_encode($this->pushMsg));        }    }}

項(xiàng)目里主要使用的功能點(diǎn)已經(jīng)講解完畢了,剩下的等有時(shí)間再整理。


關(guān)鍵詞: Swoole 云數(shù)據(jù)庫(kù) Server

 

推薦內(nèi)容

資訊

熱門產(chǎn)品

閥門品牌