/**
* 解析启动模式参数
* @param $opt
*/
static public function params_s($opt)
{
//判断传入了s参数但是值,则提示错误
if ((isset($opt["s"]) && !$opt["s"]) || (isset($opt["s"]) && !in_array($opt["s"], array("start", "stop", "restart")))) {
Main::log_write("Please run: path/to/php main.php -s [start|stop|restart]");
} if (isset($opt["s"]) && in_array($opt["s"], array("start", "stop", "restart"))) {
switch ($opt["s"]) {
case "start":
Crontab::start();
break;
case "stop":
Crontab::stop();
break;
case "restart":
Crontab::restart();
break;
}
}
}

 这里我们先分析Crontab::start()

  从这个意思我们应该知道这应该是进程启动的方法

因为crontab自己注册了引入方法,所以方法在include/Crontab.class.php中

/**
* 启动
*/
static public function start()
{
if (file_exists(self::$pid_file)) {
die("Pid文件已存在!\n");
}
self::daemon();
self::set_process_name();
self::run();
Main::log_write("启动成功");
}

  先检查pid文件是否存在,如果存在说明进程已经启动不能再次开始

self::daemon(); 在上一节,如果params_d($opt) 开启守护进程会执行swoole_process::daemon();//传送门:https://wiki.swoole.com/wiki/page/273.html

self::set_process_name();//设置进程名字 这里没有支持用户自己命名,名字为:lzm_Master

接下来执行run方法:

 /**
* 运行
*/
static protected function run()
{
self::$tasksHandle = new LoadTasks(strtolower(self::$taskType), self::$taskParams);
self::register_signal();
if (self::$checktime) {
$run = true;
Main::log_write("正在启动...");
while ($run) {
$s = date("s");
if ($s == 0) { Crontab::load_config();
self::register_timer();
$run = false;
} else {
Main::log_write("启动倒计时 " . (60 - $s) . " 秒");
sleep(1);
}
}
} else {
self::load_config();
self::register_timer();
}
self::get_pid();
self::write_pid();
//开启worker
if (self::$worker) {
(new Worker())->loadWorker();
}
}

  106行:self::$tasksHandle = new LoadTasks(strtolower(self::$taskType), self::$taskParams);//这里我们就分析LoadTasksByFile,这里放到下一讲

  107行:self::register_signal();//注册信号,用来处理进程退出

如果在客户端进行ctrl+c退出的话,会发送SIGINT信号,但是这里没做处理,那么请不要在客户端直接ctrl+c退出程序,不然的话下次就需要执行重启命令了,因为不退出

  如果受到退出信号SIGTERM就会直接调用exit2p:删除掉pid文件然后直接exit退出

还需要处理当子进程退出,为了不让程序变成僵尸进程需要进行wait处理

  这里是先判断是否在tasklist中pid是否存在,如果存在这个任务,则直接将子进程关闭,如果这个任务还有unique_list值(这里是任务里的排他数量的意思)会进行自减,杀死后扣除1,如果在load_config中会继续往taskTabel插入任务,争用这个unique字段
       如果是工作进程,那么复制一份work进程

  至于SIGUSR1信号,这里本来是应该是重新加载配置文件的,不知道为什么这里没有加上实现

/**
* 注册信号
*/
static private function register_signal()
{
swoole_process::signal(SIGTERM, function ($signo) {
self::exit2p("收到退出信号,退出主进程");
});
swoole_process::signal(SIGCHLD, function ($signo) {
while ($ret = swoole_process::wait(false)) {
$pid = $ret['pid'];
if (isset(self::$task_list[$pid])) {
$task = self::$task_list[$pid];
if ($task["type"] == "crontab") {
$end = microtime(true);
$start = $task["start"];
$id = $task["id"];
Main::log_write("{$id} [Runtime:" . sprintf("%0.6f", $end - $start) . "]");
$task["process"]->close();//关闭进程
unset(self::$task_list[$pid]);
if (isset(self::$unique_list[$id]) && self::$unique_list[$id] > 0) {
self::$unique_list[$id]--;
}
}
if ($task["type"] == "worker") {
$end = microtime(true);
$start = $task["start"];
$classname = $task["classname"];
Main::log_write("{$classname}_{$task["number"]} [Runtime:" . sprintf("%0.6f", $end - $start) . "]");
$task["process"]->close();//关闭进程
(new Worker())->create_process($classname, $task["number"], $task["redis"]);
}
}
};
});
swoole_process::signal(SIGUSR1, function ($signo) {
//TODO something
}); }

  这些都执行后,会执行Crontab::load_config();

该方法会读取到我们配置文件的读取路径中的数据,在main.php里面params_c方法会默认从ROOT_PATH . "config/crontab.php"中获取

  Crontab.class.php:line162->ParseCrontab::parse($task["rule"], $time);//这里是解析定时任务的规则返回值是每个任务的下次执行的间隔(秒级),类似linux自带的crontab的规则,这个放到后面讲解

  TickTable::set_task($ret, array_merge($task, array("id" => $id)));//这里会将读取到任务的规则写到ticktable里面
  self::register_timer();//这里才是任务调度的关键,每隔1分钟会将到下一分钟需要执行的任务插入到ticktable里面,然后每隔1s钟执行task

 下一讲:do_something方法

分析params_s方法的更多相关文章

  1. 网友"就像一支烟"山寨币分析估值方法

    [注:素材取自QQ群,2017年12月28日的聊天记录."就像一支烟"分享了自己的山寨币分析估值方法.因为删去了其他人的聊天记录,部分文字可能断章取义,仅供参考,具体情况请自行分析 ...

  2. [C语言] 数据结构-算法效率的度量方法-事前分析估算方法

    事前分析估算方法:在计算机程序编制前,依据统计方法对算法进行估算,抛开与计算机硬件软件有关的因素,一个程序的运行时间,依赖于算法的,好坏和问题的输入规模,所谓问题输入规模是指输入量的多少 推导过程,比 ...

  3. requirejs源码分析: requirejs 方法–2. context.require(deps, callback, errback);

    上一篇 requirejs源码分析: requirejs 方法–1. 主入口  中的return context.require(deps, callback, errback);  调用的是make ...

  4. 通过混合编程分析的方法和机器学习预测Web应用程序的漏洞

    通过混合编程分析的方法和机器学习预测Web应用程序的漏洞 由于时间和资源的限制,web软件工程师需要支持识别出有漏洞的代码.一个实用的方法用来预测漏洞代码可以提高他们安全审计的工作效率.在这篇文章中, ...

  5. 日志分析方法概述 & Web日志挖掘分析的方法

    日志在计算机系统中是一个非常广泛的概念,任何程序都有可能输出日志:操作系统内核.各种应用服务器等等.日志的内容.规模和用途也各不相同,很难一概而论. 本文讨论的日志处理方法中的日志,仅指Web日志.其 ...

  6. mybatis源码分析(方法调用过程)

    十一月月底,宿舍楼失火啦,搞得20多天没有网,目测直到放假也不会来了... 正题 嗯~,其实阅读源码不是为了应付面试,更重要的让你知道,大师是怎样去写代码的,同样是用Java,为啥Clinton Be ...

  7. tomcat启动(三)Catalina分析-load方法分析

    load()方法按从上到下顺序分析(主要分析本人所没学过的知识点,其它略过...). Digester类作用 使用sax技术对xml进行解析 未开始解析时Digester.push(this)这个用来 ...

  8. requirejs源码分析: requirejs 方法–1. 主入口

    该方法是 主要的入口点 也是最常用的方法. req = requirejs = function (deps, callback, errback, optional) { //Find the ri ...

  9. 【转载】WEB系统性能问题的分析定位方法

    以一个典型的WEB系统来举例,性能问题一般体现在客户端请求后的响应时间上.在性能测试过程中,即压力增大到某个程度后,响应时间指标迅速增长.但如那篇文章所说,这只能叫做一个现象,测试人员需要找到问题所在 ...

随机推荐

  1. SPSS-生存分析

    生存分析 定义:一些医学事件所经历的时间:从开始观察到事件发生的时间,不是短期内可以明确判断的.针对这类生存资料的分析方法叫生存分析.生存分析的基本概念1.终点事件终点事件outcome event: ...

  2. java fastJson

    // 大区的数据 String cityList = "[{'title':'华北','value':'1','children':[{'title':'山东','value':'1.1', ...

  3. Genomic signatures of evolutionary transitions from solitary to group living(独居到社会性的转变)

    1.摘要 群居性的进化是进化的主要过渡之一,但其背后的基因组变化是未知的.我们比较了10种蜜蜂的基因组,它们的社会复杂性各不相同,代表了社会进化中的多种独立过渡,并报告了三项主要发现. 第一,许多重要 ...

  4. spring ContentNegotiationManagerFactoryBean 内容协商

    一.什么是内容协商 简单点说,就是同一资源,可以有多种表现形式,比如xml.json等,具体使用哪种表现形式,是可以协商的. 这是RESTfull的一个重要特性,Spring Web MVC也支持这个 ...

  5. 使用JavaMail发送邮件-no object DCH for MIME type multipart/mixed报错解决

    最近需要实现一个使用Spring schedule按一定时间间隔自动触发条件发送邮件的功能,在开发的过程中,是按照先测试能发出text/html文本邮件,然后测试添加附件发送邮件,我碰到的问题是,文本 ...

  6. java中map接口hashMap以及Enty之间的用法和关系

    java中map接口hashMap以及Enty之间的转换 首先说的是map接口: Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value ...

  7. new.target

    [new.target] The new.target property lets you detect whether a function or constructor was called us ...

  8. 关于U3D图片的压缩格式

    http://blog.sina.com.cn/s/blog_930ffa0b0102vass.html

  9. 解题(MiGong--迷宫问题(深度搜索))

    题目描述 定义一个二维数组N*M(其中2<=N<=10;2<=M<=10),如5 × 5数组下所示: int maze[5][5] = { 0, 1, 0, 0, 0, 0,  ...

  10. flash Air 在同一个目录下面创建txt,写入字

    import flash.filesystem.*; var file:File=new File(File.applicationDirectory.nativePath + '/HelloWorl ...