当前位置: 代码网 > it编程>编程语言>Php > Swoole webSocket消息服务系统代码设计详解

Swoole webSocket消息服务系统代码设计详解

2024年05月19日 Php 我要评论
概述已经swoole系列的第二篇知识点了,前一篇主要的针对处理的是方案设计,这一篇主要是代码实现的内容,主要介绍高性能的原因已经实现,编程框架使用easyswoole。swoole 与 easyswo

概述

已经swoole系列的第二篇知识点了,前一篇主要的针对处理的是方案设计,这一篇主要是代码实现的内容,主要介绍高性能的原因已经实现,编程框架使用easyswoole。

swoole 与 easyswoole

swoole属于php中的一个超级扩展,它会接管php的进程,管理和分配worker,但他依赖 php-cli模式。swoole和yaf有相似的地方,它们都是以守护进程的模式、常驻内存的方式达到提高处理性能。

swoole内置了tcp、udp、websocket、协程、异步、redis/mysql链接池等高效开发手段和方法,当然对于新模式也有新的挑战,比如swoole不能使用die,会致使worker滑落,协程使用后要注意使用回调的过程,如果对php的基础知识不了解的同学,可以翻看我之前的php博客里的总结,这里就不过多叙述了。

easyswoole是一款非常简单上手易操作的swoole框架,上线2年多以来经得住生产环境的考验,官网文档写的也很详细,还有专门解答的qq群,大佬们会解答很多问题。

安装easyswoole框架

之前我使用composer进行安装的(composer是php中管理依赖包的工具,和node里面的npm,python的pip 一样),现在都使用docker镜像直接操作了。

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

项目初始目录结构:

├── easyswooleevent.php
├── bootstrap.php
├── composer.json
├── composer.lock
├── dev.php
├── easyswoole
├── produce.php
└── vendor

注册服务 与启动加载

1.在easyswooleevent.php文件中加载初始化需要的mysql、redis配置文件,所有需要的服务都需要在启动文件中进行注册,才能使用。

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.注册mysql连接池,mysql连接池主要设置参数,

<?php
use easyswoole\orm\db\config as dbconfig;
use easyswoole\orm\db\connection;
use easyswoole\orm\dbmanager;
return [
    //mysql数据库配置
    'mysql-msg' => [
        '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',    //设置获取连接池对象超时时间
        'checkout' => 30 * 1000,  //设置检测连接存活执行回收和创建的周期
        'maxidletime' => 15,       //连接池对象最大闲置时间(秒)
        'maxobjectnumber' => 100,       //设置最大连接池存在连接对象数量
        'minobjectnumber' => 5,        //设置最小连接池存在连接对象数量
        'autoping' => 5,        //设置自动ping客户端链接的间隔
    ],
];

3.注册redis链接池

use \easyswoole\redis\config\redisconfig;
use \easyswoole\redispool\redispool;
$redisconf = globalconfig::getinstance()->getconf('redis');
redispool::getinstance()->register(new redisconfig($redisconf),'redis');

4.注册自定义log

use  \easyswoole\easyswoole\logger;
logger::getinstance(new \app\log\loghandel());

5.我的项目里还使用了crontab模块

use swoole\coroutine\scheduler;
use easyswoole\easyswoole\crontab\crontab;
//用户通知队列
crontab::getinstance()->addtask(\app\crontab\pushusernoticemsg::class);

6.添加热启动

swoole的服务属于常驻内存加载类型的服务,所以每次修改代码后都需要重启服务,所以为了方便,添加了热加载目录,热加载原理就是当检测到指定目录有代码更新时,用传递信号的方式进行,指挥进程进行重新加载。

$hotreloadoptions = new \easyswoole\hotreload\hotreloadoptions;
$hotreload = new \easyswoole\hotreload\hotreload($hotreloadoptions);
$hotreloadoptions-&gt;setmonitorfolder([easyswoole_root . '/app']);
$server = servermanager::getinstance()-&gt;getswooleserver();
$hotreload-&gt;attachtoserver($server);

7.启动/停止服务,参数说明

-mode 说明启动服务类型 -d 以守护进程的方式

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

异步和 db(redis/mysql)使用

1.高性能的异步操作

如果是不依赖于结果的计算,异步操作提高性能的有效手段之一,异步操作不需要等待结果,更好的利用cpu和i/o传输。

use easyswoole\easyswoole\task\taskmanager;
taskmanager::getinstance()-&gt;async(function () use ($tablename,$data) {
    // todo code ...
});
  • redis/mysql使用

在高并发情况下,资源浪费的占用时间越短越好,可以提高程序的服务效率。在orm默认情况下是使用defer方法获取pool内的连接资源,并在协程退出时自动归还,在此情况下,在带来便利的同时,会造成不必要资源的浪费。

我们可以使用invoke方式,让orm查询结束后马上归还资源,可以提高资源的利用率。

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-&gt;zadd(self::push_msg_author_notice_system, $uid, $fd);
    }, self::redis_conn_name);
}
## defer方式
$redis = \easyswoole\redispool\redispool::defer('redis');
$data = $redis-&gt;lrange(self::push_msg_comment_delay_lists, 0, 1000);

websocket服务

1.websocket协议是什么

websocket协议是基于tcp的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。

在没有websocket协议之前,在网页中,实现一个聊天室只能使用ajax 不断轮询,请求服务器是否有数据产生,而这样的实现方法会出现一系列的问题:

  • 如果轮询时间间隔太短,会导致客户端和服务端在一个时间段内不断的进行http tcp的握手/挥手动作和http 请求头,响应头的传输,大量消耗服务器资源,如果用户量大的情况,会造成服务器的繁忙以至于宕机
  • 客户端每次只能通过发送http 请求获得服务器是否有数据返回,且数据的及时性无法保证

正因为在这种情况下,所以websocket出现了,它只需要一次http握手,就可以保持一个长连接,使得服务器可以主动发送消息给客户端,大大减少了轮询机制的消耗。

2.websocket协议实现原理

在实现websocket连线过程中,需要通过浏览器发出websocket连线请求,然后服务器发出回应,这个过程通常称为握手 。

在 websocket api,浏览器和服务器只需要做一个握手的动作,然后,浏览器和服务器之间就形成了一条快速通道。两者之间就直接可以数据互相传送。在此websocket 协议中,为我们实现即时服务带来了两大好处:

  • header: 互相沟通的header是很小的-大概只有 2 bytes
  • server push: 服务器的推送,服务器不再被动的接收到浏览器的请求之后才返回数据,而是在有新数据时就主动推送给浏览器。
//$fd,指的是系统里的文件描述符fd
use easyswoole\easyswoole\servermanager;
$server = servermanager::getinstance()->getswooleserver();
$server->push($fd,json_encode($messagedata));
//获取当前链接的详细信息
$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));
        }
    }
}

以上就是swoole websocket消息服务系统代码设计详解的详细内容,更多关于swoole websocket消息服务的资料请关注代码网其它相关文章!

(0)

相关文章:

版权声明:本文内容由互联网用户贡献,该文观点仅代表作者本人。本站仅提供信息存储服务,不拥有所有权,不承担相关法律责任。 如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 2386932994@qq.com 举报,一经查实将立刻删除。

发表评论

验证码:
Copyright © 2017-2025  代码网 保留所有权利. 粤ICP备2024248653号
站长QQ:2386932994 | 联系邮箱:2386932994@qq.com