EasySwoole 服务启动过程以及主体设计流程源码解析

news/2023/12/1 7:31:25

EasySwoole 服务启动过程以及主体设计流程源码解析

本文主要讲解EasySwoole 服务的启动过程,会通过源码片段讲解主体的设计流程

命令启动

当我们通过php easyswoole start启动EasySwoole 服务时,命令真正到达的文件是 easyswoole项目\vendor\easyswoole\easyswoole\bin\easyswoole,命令start执行的整体流程如下图:

整体流程

主要方法为:serverStart($options);,其重要执行代码如下:

$conf    = Conf::getInstance();
$inst    = Core::getInstance()->initialize();
$inst->run();
  • 初始化Conf,即Config对象(Config类为一个单例对象),加载全局配置信息,默认配置Config.php内容如下:
return [
    'SERVER_NAME'=>"EasySwoole",
    'MAIN_SERVER'=>[
        'HOST'=>'0.0.0.0',
        'PORT'=>9501,
        'SERVER_TYPE'=>\EasySwoole\Core\Swoole\ServerManager::TYPE_WEB_SERVER,
        'SOCK_TYPE'=>SWOOLE_TCP,//该配置项当为SERVER_TYPE值为TYPE_SERVER时有效
        'RUN_MODEL'=>SWOOLE_PROCESS,
        'SETTING'=>[
            'task_worker_num' => 8, //异步任务进程
            'task_max_request'=>10,
            'max_request'=>5000,//强烈建议设置此配置项
            'worker_num'=>8
        ],
    ],
    'DEBUG'=>true,
    'TEMP_DIR'=>null,//若不配置,则默认框架初始化
    'LOG_DIR'=>null,//若不配置,则默认框架初始化
    'EASY_CACHE'=>[
        'PROCESS_NUM'=>1,//若不希望开启,则设置为0
        'PERSISTENT_TIME'=>0//如果需要定时数据落地,请设置对应的时间周期,单位为秒
    ],
    'CLUSTER'=>[
        'enable'=>false,
        'token'=>null,
        'broadcastAddress'=>['255.255.255.255:9556'],
        'listenAddress'=>'0.0.0.0',
        'listenPort'=>'9556',
        'broadcastTTL'=>5,
        'nodeTimeout'=>10,
        'nodeName'=>'easySwoole',
        'nodeId'=>null
    ]
];
  • 执行入口文件Code.php对象的initialize()方法
  • 执行入口文件Code.php对象的run()方法

ps:此处插入说明一个点,EasySwoole中单例类都复用同一个trait

trait Singleton
{
    private static $instance;

    static function getInstance(...$args)
    {
        if(!isset(self::$instance)){
            self::$instance = new static(...$args);
        }
        return self::$instance;
    }
}

入口文件

Easywechat 真实入口文件为EasySwoole\Core\Core,上述已经说到命令启动时,执行了以下代码:

Core::getInstance();
$inst = Core::getInstance()->initialize();
$inst->run();

在整个EasySwoole生命周期中,Core对象只会被实例化一次,Code的初始化做了如下操作:

public function __construct()
    {
        defined('SWOOLE_VERSION') or define('SWOOLE_VERSION',intval(phpversion('swoole')));
        defined('EASYSWOOLE_ROOT') or define('EASYSWOOLE_ROOT',realpath(getcwd()));
        if(file_exists(EASYSWOOLE_ROOT.'/EasySwooleEvent.php')){
            require_once EASYSWOOLE_ROOT.'/EasySwooleEvent.php'; //引入全局初始化事件类
        }
        $this->sysDirectoryInit(); //设置temp目录和log目录,路径可配置化
    }
  • 定义了全局宏SWOOLE_VERSIONEASYSWOOLE_ROOT
  • 引入了全局初始化事件类EasySwooleEvent.php
  • $this->sysDirectoryInit(); 设置temp目录和log目录,路径可配置化

Core类中的initialize方法:

    public function initialize():Core
    {
        Di::getInstance()->set(SysConst::VERSION,'2.1.2');
        Di::getInstance()->set(SysConst::HTTP_CONTROLLER_MAX_DEPTH,3);
        EasySwooleEvent::frameInitialize();
        $this->errorHandle();
        return $this;
    }
  • DI容器注入SysConst::VERSIONSysConst::HTTP_CONTROLLER_MAX_DEPTH 的值
  • 执行全局事件类EasySwooleEvent::frameInitialize();事件
  • $this->errorHandle();注册系统中的set_error_handler、register_shutdown_function

Core类的run方法为核心功能:

public function run():void
{
    ServerManager::getInstance()->start();
}
  • 实例化ServerManager类,并执行start() 启动整个服务

服务管理类 ServerManager

ServerManager是一个单例对象,在整个EasySwoole生命周期中,ServeManager对象只会被实例化一次.
ServeManagerrun 方法干了下面几件事:

    public function start():void
    {
        $this->createMainServer();
        Cache::getInstance();
        Cluster::getInstance()->run();
        CronTab::getInstance()->run();
        $this->attachListener();
        $this->isStart = true;
        $this->getServer()->start();
    }
  • createMainServer() 创建主服务
  • 初始化缓存服务 cache,添加对应的CacheProcess。(Easyswoole的缓存服务是基于swoole_process的管道通信,后续会专门解析下系统组件cache的源码)
  • Cluster集群模式的注册 (有兴趣的可以通过链接看看)
  • CronTab 服务开启,后面说下crontab的使用
  • attachListener事件监听,子服务多端口监听
  • $this->getServer()->start(); 调用swoole_server的start方法,正式启动Easyswoole服务

ServerManager 类的createMainServer()方法:

(1)读取配置,创建对应的swoole_server服务

            case self::TYPE_SERVER:{
                $this->mainServer = new \swoole_server($host,$port,$runModel,$sockType);
                break;
            }
            case self::TYPE_WEB_SERVER:{
                $this->mainServer = new \swoole_http_server($host,$port,$runModel,$sockType);
                break;
            }
            case self::TYPE_WEB_SOCKET_SERVER:{
                $this->mainServer = new \swoole_websocket_server($host,$port,$runModel,$sockType);
                break;
            }
            default:{
                Trigger::throwable(new \Exception("unknown server type :{$conf['SERVER_TYPE']}"));
            }
        }

(2)注册事件,onWorker、onTask、onFinish、onRequest等;还有easySwoole事件mainServerCreate,开发者可以在mainServerCreate事件设置Crontab 服务等

        $register = new EventRegister();//事件容器
        $this->finalHook($register);
        EasySwooleEvent::mainServerCreate($this,$register);
        $events = $register->all();

(3)事件注册的过程中,还做了如下操作:实例化对象池。开发者可以通过配置,在此实例化mysql连接池等:

        //实例化对象池管理
        PoolManager::getInstance();
        PoolManager::getInstance()->__workerStartHook($workerId);

(4)在onRequest事件中,还执行了EasySwooleEventonRequestafterAction,开发者可以在此自定义处理代码,如日志统一刷出等

         EasySwooleEvent::onRequest($request_psr,$response_psr);
         $dispatcher->dispatch($request_psr,$response_psr);
         EasySwooleEvent::afterAction($request_psr,$response_psr);

ServerManagerCache::getInstance() 全局跨进程Cache的注册:

    function __construct()
    {
        $num = intval(Config::getInstance()->getConf("EASY_CACHE.PROCESS_NUM"));
        if($num <= 0){
           return;
        }
        $this->cliTemp = new SplArray();
        //若是在主服务创建,而非单元测试调用
        if(ServerManager::getInstance()->getServer()){
            //创建table用于数据传递
            TableManager::getInstance()->add(self::EXCHANGE_TABLE_NAME,[
                'data'=>[
                    'type'=>Table::TYPE_STRING,
                    'size'=>10*1024
                ],
                'microTime'=>[
                    'type'=>Table::TYPE_STRING,
                    'size'=>15
                ]
            ],2048);
            $this->processNum = $num;
            for ($i=0;$i < $num;$i++){
                ProcessManager::getInstance()->addProcess($this->generateProcessName($i),CacheProcess::class);
            }
        }
    }

Cache 服务基于 swoole_table 实现全局数据共享和传递。

以上是EasySwoole服务启动过程中的主体设计,其中包括了各种组件的实例化,如PoolManager(对象池)、cache、CronTab等。


http://www.niftyadmin.cn/n/1978945.html

相关文章

[SQL Server Mobile 开发基础] ppt 和 demo

昨天参加了广州.NET俱乐部的讲义活动&#xff08;详情&#xff1a;广州.NET俱乐部--8月12日活动通知&#xff09;&#xff0c;这次活动的主题是 Mobile 开发日。我很荣幸能够在这次活动中跟大家分享自己在 Windows Mobile 开发方面的一些心得体会。第一次在广州微软的 Windows …

php读取excel中的时间转换问题

今天要做数据导入&#xff1a;把2012-5-10 16:00:00 读入到php中后变成了41039.666666667 这种Excel列的单元格格式为日期单元格式&#xff0c;如果是文本格式则会得到我们想要的原样的字符串类型。 转换方法一&#xff1a; $t 41807; //读取到的值 $n intval(($t - 25569…

琪琪格携手窦唯亮相“摇滚世界杯”引公司不满

超女”和“世界杯”是时下娱乐圈最热门的话题&#xff0c;而不少超女也借机摇身一变成为各大世界杯活动力邀的足球宝贝。不过许多超女没有打招呼就擅自作主的做法令天娱公司高层颇有微词&#xff0c;而琪琪格作为粉丝网足球宝贝代表将与窦唯一同亮相“摇滚世界杯”的举动引起天…

Linux 单独安装mysqldump

yum -y install holland-mysqldump.noarch mysqldump备份简单操作&#xff1a; mysqldump -h[ip] -P[端口号] -u[用户名] -p[密码] 数据库名 表名 >导出的文件名.sql mysqldump -h[ip] -P[端口号] -u[用户名] -p[密码] 数据库名 表名1 表名2 表名3 | gzip >导出…

JPA 时间查询

1.Between - findByStartDateBetween … where x.startDate between ?1 and ?2 2.LessThan/LessThanEqual LessThan - findByEndLessThan … where x.start< ?1 LessThanEqual findByEndLessThanEqual … where x.start < ?1 3.GreaterThan/GreaterThanEqual Greater…

linux lftp与sftp使用

安装lftp&#xff1a; yum -y install lftp lftp简介 lftp 是一个功能强大的下载工具&#xff0c;它支持访问文件的协议: ftp, ftps, http, https, hftp, fish.(其中ftps和https需要在编译的时候包含openssl库)。llftp的界面非常想一个shell: 有命令补全&#xff0c;历史记录…

让我坚持“摸鱼”的旗号:斜杠创业家 | 摸鱼系列

坚持每周写文章已数月&#xff0c;在上周终于第一次收到了读者的来信&#xff0c;一方面因为非常珍视第一次收到的来信&#xff0c;另一方面近期“画饼系列”的市场反馈实在较烂&#xff0c;所以希望可以通过和读者进行互动的形式&#xff0c;拯救一下系列的阅读量。 问题一&am…

从写博客到写书

在[征询意见]关于博客园与出版社合作出书之后&#xff0c;我一直在思考这样的问题&#xff1a;如何让大家从写博客迈向写书? 如果有一天&#xff0c;在书店里看到很多园子里的朋友写的书&#xff0c;那是多么让人兴奋啊!我想大多数人写博客、写书都是基于这样一个基本目的&…

获取表单信息并转json

var fromData $(#voiceMoney).serializeArray(); var paramData {}; $.each(fromData,function(i, v) {paramData[v.name] v.value; });

阿里巴巴登顶全球企业创新榜,被美国四大互联网公司视为头号对手

在最新发布的毕马威2018年度创新报告中&#xff0c;阿里巴巴被评为地球上最具科技颠覆力的公司。排在阿里巴巴之后的&#xff0c;是Facebook、亚马逊、谷歌等美国科技巨头。 毕马威这份科技创新报告中在科技界和商业界颇有影响力。这家全球著名的会计师事务所&#xff0c;在深度…

SqlServer和Oracle的数据类型在.NETFramework中的对应数据类型.

http://msdn2.microsoft.com/zh-cn/library/4e5xt97a.aspx 转载于:https://www.cnblogs.com/guaiguosh/archive/2006/09/01/492001.html

windows 命令行快速删除文件

del /a /f /s /q * *为通配符 /a /f 是强制删除所有属性的文件 /q是无需确认直接删除 要是再加上/s开关&#xff0c;就可以删除子文件加中的文件 例&#xff1a; D:\md5_path\0b>del /a /f /s /q *

Linux/Centos 安装oracle报错“调用makefile '/oracle/produc

解决centos7/redhat7安装oracle11g到%70报错问题Linux/Centos 安装oracle报错“调用makefile /oracle/product/11.2.0/dbhome_1/sysman/lib/ins_emagent.mk的目标” 解决办法如下图为报错&#xff1a;解决办法&#xff1a; #vim/oracle-11g/app1/oracle/product/11.2.0/dbhome_…

php 字符串去除Html所有标签、空格以及空白

//字符串去除Html所有标签、空格以及空白 function cutstr_html($string){$string strip_tags($string);$string trim($string);$string ereg_replace("\t","",$string);$string ereg_replace("\r\n","",$string);$string ereg_r…

生命之旅

第一篇科幻小说。以“锋寒”&#xff08;源于《大唐双龙传》中的角色跋锋寒&#xff0d;&#xff0d;我很喜欢这个人&#xff09;为笔名发于1999年《科幻世界》第5期。感谢科幻世界的编辑&#xff0c;当时人小不懂事情&#xff0c;不知道感谢。                …

tp3.2 与tp5 tp与yii tp与laravel

tp5和tp3.2的区别: 1. URL和路由的变化 5.0的URL访问不再支持普通URL模式&#xff0c;路由也不支持正则路由定义&#xff0c;而是全部改为规则路由配合变量规则&#xff08;正则定义&#xff09;的方式&#xff1a; 主要改进如下; 增加路由变量规则&#xff1b; 增加组合变量支…
最新文章