php 热更新,Laravel 使用 Swoole 代码热更新方案

业务背景

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

匹配流程如下

对匹配者的鉴权(握手事件处理)

匹配的业务逻辑(比如男只能匹配到女,这块也是需要热更新,open事件处理)

匹配成功返回数据,关闭连接

再往后就是nodejs去提供服务

想要达到的目的

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

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

安装swoole和inotify

自己绘制的"设计图"

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

e28a0eec55b7db754463725f6b0f3215.png

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;

}

bac72c4c360d2f328dacd68820372fb1.png

关于守护我用的是supervisor

本作品采用《CC 协议》,转载必须注明作者和本文链接

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值