摘要:最近使用基于开发的框架开发项目,碰到一个需求,就是想要做项目初始化处理。当初始化处理完成前,不想让处理请求。事件定义是一个从之间的数字,表示这个进程的那这个就好办了,直接判断为的去触发项目初始化事件。
最近使用基于 Swoole 开发的 imi 框架 开发项目,碰到一个需求,就是想要做项目初始化处理。当初始化处理完成前,不想让 Swoole 处理请求。因为可能有一些值没有加载进来,处理请求极有可能出现问题。
下面给出了思考过程及解决问题的demo代码。
首先分析了一下,Swoole 是多进程模式运行的,分为 Master、Manager、Worker 进程。
Master 进程就是我们启动服务的 cli 命令文件所在进程,在这里面初始化有一个问题,这里所有加载的类、全局变量,其它 Worker 进程里都可以使用,无法热重启生效。
Manager 进程的情况基本和上面差不多。
那么只有在 Worker 进程做处理了,但如果写在 WorkerStart 事件里,每个 Worker 进程都会去执行。
WorkerStart 事件定义:
function onWorkerStart(swoole_server $server, int $worker_id);
$worker_id是一个从0-$worker_num之间的数字,表示这个Worker进程的ID
那这个就好办了,直接判断workerid为0的去触发项目初始化事件。剩下还有一个问题就是,如何在初始化执行完成前,让所有 Worker 进程暂时都不处理请求。
思考并尝试了一下,这个问题可以通过协程挂起来解决,demo 代码如下:
on("WorkerStart", function(swoole_http_server $server, $workerId){ $initFlagFile = __DIR__ . "/init.flag"; if(0 === $server->worker_id && (!is_file($initFlagFile) || file_get_contents($initFlagFile) != $server->manager_pid)) { // 处理项目初始化事件 initApp(); // 写入文件,保证不再重复触发项目初始化事件 file_put_contents($initFlagFile, $server->manager_pid); // 当前worker进程恢复协程 resumeCos(); // 通知其它worker进程 for($i = 1; $i < $server->setting["worker_num"]; ++$i) { $server->sendMessage("init", $i); } } }); $http->on("PipeMessage", function(swoole_http_server $server, $srcWorkerId, $data) { if(0 === $srcWorkerId && "init" === $data && !defined("APP_INITED")) { // 其它worker进程恢复协程 resumeCos(); } }); $http->on("request", function (swoole_http_request $request, swoole_http_response $response) { // 判断未初始化完毕,则挂起协程 if(!defined("APP_INITED")) { $GLOBALS["WORKER_START_END_RESUME_COIDS"][] = Coroutine::getuid(); Coroutine::suspend(); } $response->header("content-type", "text/html;charset=utf-8"); $response->end("IMI 是一款基于 Swoole 开发的协程 PHP 开发框架,拥有常驻内存、协程异步非阻塞IO等优点。官方网站:https://imiphp.com"); }); $http->start(); /** * 处理项目初始化事件,比如这里延时5秒,模拟初始化处理 * * @return void */ function initApp() { $count = 5; for($i = 0; $i < $count; ++$i) { echo "initing ", ($i + 1), "/", $count, PHP_EOL; sleep(1); } } /** * 恢复协程 * * @return void */ function resumeCos() { define("APP_INITED", true); $coids = $GLOBALS["WORKER_START_END_RESUME_COIDS"] ?? []; fwrite(STDOUT, "suspend co count: " . count($coids) . PHP_EOL); foreach($coids as $id) { Coroutine::resume($id); } }
通过在 request 事件中判断是否初始化完毕,如果没有初始化完成,则挂起当前协程,将协程ID加入全局变量。
当第0个 worker 进程执行完初始化后,通过向其他 worker 进程发送消息,唤醒曾经挂起的协程们,在初始化期间进来的请求,这时候会被执行。
原文地址:https://blog.yurunsoft.com/a/...
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/30870.html
摘要:是一个基于扩展实现的轻量级高性能的常驻内存型的和应用服务框架高度封装了,,服务器,以及基于实现可扩展的服务,同时支持包方式安装部署项目。基于实用,抽象事件处理类,实现与底层的回调的解耦,支持同步异步调用,内置等常用组件等。 swoolefy swoolefy是一个基于swoole扩展实现的轻量级高性能的常驻内存型的API和Web应用服务框架,高度封装了http,websocket,ud...
摘要:和服务关系最密切的进程是中的进程组,绝大部分业务处理都在该进程中进行。随后触发一个事件各组件通过该事件进行配置文件加载路由注册。事件每个请求到来时仅仅会触发事件。服务器生命周期和服务基本一致,详情参考源码剖析功能实现 作者:bromine链接:https://www.jianshu.com/p/4c0...來源:简书著作权归作者所有,本文已获得作者授权转载,并对原文进行了重新的排版。S...
摘要:官网源码解读号外号外欢迎大家我们开发组定了一个就线下聚一次的小目标里面的框架算是非常重的了这里的重先不具体到性能层面主要是框架的设计思想和框架集成的服务让框架可以既可以快速解决很多问题又可以轻松扩展中的框架有在应该无出其右了这次解读的源码 官网: https://www.swoft.org/源码解读: http://naotu.baidu.com/file/8... 号外号外, 欢迎大...
摘要:以上是服务启动过程中的主体设计,其中包括了各种组件的实例化,如对象池等。 EasySwoole 服务启动过程以及主体设计流程源码解析 本文主要讲解EasySwoole 服务的启动过程,会通过源码片段讲解主体的设计流程 命令启动 当我们通过php easyswoole start启动EasySwoole 服务时,命令真正到达的文件是 easyswoole项目vendoreasyswool...
摘要:基于扩展实现真正的数据库连接池这种方案中,项目占用的连接数仅仅为。一种是连接暂时不再使用,其占用状态解除,可以从使用者手中交回到空闲队列中这种我们称为连接的归队。源码剖析系列目录 作者:bromine链接:https://www.jianshu.com/p/1a7...來源:简书著作权归作者所有,本文已获得作者授权转载,并对原文进行了重新的排版。Swoft Github: https:...
阅读 1540·2023-04-26 02:43
阅读 2819·2021-11-11 16:54
阅读 1324·2021-09-23 11:54
阅读 1109·2021-09-23 11:22
阅读 2294·2021-08-23 09:45
阅读 830·2019-08-30 15:54
阅读 3076·2019-08-30 15:53
阅读 3158·2019-08-30 15:53