【swoole】Laravel 框架使用 Swoole 代码热更新

业务背景

做的是一款游戏匹配的 App,PHP 使用 swoole 创建 websocket 提供游戏的匹配服务

匹配流程如下

  • 对匹配者的鉴权 (握手事件处理)
  • 匹配的业务逻辑 (比如男只能匹配到女,这块也是需要热更新,open 事件处理)
  • 匹配成功返回数据,关闭连接
  • 再往后就是 nodejs 去提供服务

想要达到的目的

在不重启服务的情况下,改变了匹配的业务逻辑代码的情况下自动热更新代码

关于热更新 swoole 官方文档

其实核心就是说你要热更新的代码必须在 onWorkerStart 事件中引入

安装 swoole 和 inotify

自己绘制的 "设计图"

如果你使用 artisan 启动 swoole 服务的话,可能会热更新失败,因为在 onWorkerStart, 之前已经载入太多类

【swoole】Laravel 框架使用 Swoole 代码热更新_第1张图片

index

设置常量同时实例化 MatchServer 来启动服务

require 'MatchServer.php';
if (php_sapi_name() != 'cli') die('请用cli模式启动');
define('ROOT_PATH',dirname(dirname(dirname(__DIR__))).'/');
define('PORT',20005);
$server = new MatchServer();

MatchServer

class MatchServer{
    private $server;
    protected $application;

    function __construct ()
    {
        // 创建swoole_table,用于进程间数据共享
        $table = new swoole_table(1024);
        $table->column('fd', swoole_table::TYPE_INT);
        $table->column('uid', swoole_table::TYPE_INT);
        $table->column('gameType', swoole_table::TYPE_STRING, 256);
        $table->column('data', swoole_table::TYPE_STRING, 256);
        $table->create();

        $this->server = new swoole_websocket_server("0.0.0.0", PORT);
        $this->server->table = $table;

        // 注册回调事件
        $this->server->on('handShake', array($this, 'onHandShake'));
        $this->server->on('workerStart', array($this, 'onWorkerStart'));
        $this->server->on('open', array($this, 'onOpen'));
        $this->server->on('message', array($this, 'onMessage'));
        $this->server->on('close', array($this, 'onClose'));

        $this->server->start();
    }

    /**
     * 处理握手
     * 
     * @param swoole_http_request  $request
     * @param swoole_http_response $response
     *
     * @return bool
     */
    public function onHandShake (\swoole_http_request $request, \swoole_http_response $response)
    {
        if(参数校验不通过)
        {
            $response->end();
            return false;
        }
        //swoole握手环节,因为我的匹配是在open事件处理,当自己处理握手之后,不会自动调用open事件,需自己调用

        // 握手环节代码..太多..考虑到篇幅问题,不贴了..大家可以去swoole手册搜索
        $this->onOpen($this->server, $request);

        return true;
    }

    /**
     * 载入框架入口文件,并设置inotify热更新目录
     *
     * @param $server
     * @param $worker_id
     */
    public function onWorkerStart ($server, $worker_id)
    {
        // 载入框架入口文件
        require ROOT_PATH.'public/index.php';
        // 实例化业务逻辑类
        $this->application = new MatchApplication();
        if ($worker_id == 0) {
                // 设置热更新目录
                $dir = app_path('Game/Match');
                $list[] = $dir;
                foreach (array_diff(scandir($dir), array('.', '..')) as $item) {
                        $list[] = $dir.'/'.$item;
                }

                $notify = inotify_init();
                foreach ($list as $item) {
                        inotify_add_watch($notify, $item, IN_CREATE | IN_DELETE | IN_MODIFY);
                }
                swoole_event_add($notify, function () use ($notify,$server) {
                        $events = inotify_read($notify);
                        if (!empty($events)) {
                                // 执行swolle reload
                                $server->reload();
                        }
                });
        }
    }

    /**
     * 处理匹配
     * 
     * @param $server
     * @param $request
     */
    public function onOpen ($server, $request)
    {
        // 调用业务逻辑类的onOpen
        $this->application->onOpen($server,$request);
    }

    public function onMessage ($server, $frame){}

     /**
     * 关闭连接同时删除swoole_table数据
     * 
     * @param $server
     * @param $fd
     */
    public function onClose ($server, $fd)
    {
        // 由于我进程间的数据共享用的swoole_table,所以连接关闭,需要删除数据
        if ($server->table->exist($fd)) {
            $server->table->del($fd);
        }
    }
}

MatchApplication

/**
 * 处理匹配业务逻辑
 * 
 * @param $server
 * @param $request
 */
public function onOpen ($server, $request)
{
    $fd = $request->fd;
    // 处理业务逻辑......
    $server->push($fd,$data);
    $server->close($fd);
}

启动服务

$ php Index.php

确认 onWorkerStart 之前没有载入你要热更新的代码

public function onWorkerStart ($server, $worker_id)
{
    print_r(get_included_files());
    return;
}


更多学习内容可以访问【对标大厂】精品PHP架构师教程目录大全,只要你能看完保证薪资上升一个台阶(持续更新)

以上内容希望帮助到大家,很多PHPer在进阶的时候总会遇到一些问题和瓶颈,业务代码写多了没有方向感,不知道该从那里入手去提升,对此我整理了一些资料,包括但不限于:分布式架构、高可扩展、高性能、高并发、服务器性能调优、TP6,laravel,YII2,Redis,Swoole、Swoft、Kafka、Mysql优化、shell脚本、Docker、微服务、Nginx等多个知识点高级进阶干货需要的可以免费分享给大家,需要的可以点击链接领取进阶PHP月薪30k>>>架构师成长路线【视频、面试文档免费获取】

你可能感兴趣的:(【swoole】Laravel 框架使用 Swoole 代码热更新)