php-fpm有三种定时器

1)主进程接收到用户的信号,例如sigusr,主进程执行kill(子进程号,sigquit),的同时,设置定时器,在一个无限循环里如果当前时间 大于或等于 该定时器的过期时间,则主进程执行kill(子进程号,sigterm);

2)对于在php-fpm里设置了request_terminate_timeout 和request_slowlog_timeout

  注:set_time_limit()和max_execution_time只影响脚本本身执行的时间。

  (这两个参数在php.ini中)任何发生在诸如使用system()的系统调用,流操作,数据库操作等的脚本执行的最大时间不包括其中.

  建立定时器是在函数fpm_event_loop中的fpm_pctl_heartbeat函数,调用前有个判断条件 fpm_globals.heartbeat需要大于0

在解析php-fpm.conf文件中,fpm_globals.heartbeat最终为request_terminate_timeout和request_slowlog_timeout较小的一个

static int fpm_conf_process_all_pools(){
//省略无关代码 if (wp->config->request_terminate_timeout) {
fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_terminate_timeout * ) / ) : (wp->config->request_terminate_timeout * ) / ;
} if (wp->config->request_slowlog_timeout) {
fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_slowlog_timeout * ) / ) : (wp->config->request_slowlog_timeout * ) / ; }
}

/* a minimum of 130ms heartbeat for pctl */

#define FPM_PCTL_MIN_HEARTBEAT (130)

void fpm_pctl_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
static struct fpm_event_s heartbeat;
struct timeval now; if (fpm_globals.parent_pid != getpid()) {
return; /* sanity check */
} if (which == FPM_EV_TIMEOUT) {
fpm_clock_get(&now);
fpm_pctl_check_request_timeout(&now);
return;
} /* ensure heartbeat is not lower than FPM_PCTL_MIN_HEARTBEAT */ //这里又和默认的相比,取最大的
fpm_globals.heartbeat = MAX(fpm_globals.heartbeat, FPM_PCTL_MIN_HEARTBEAT); /* first call without setting to initialize the timer */
zlog(ZLOG_DEBUG, "heartbeat have been set up with a timeout of %dms", fpm_globals.heartbeat);
fpm_event_set_timer(&heartbeat, FPM_EV_PERSIST, &fpm_pctl_heartbeat, NULL);
fpm_event_add(&heartbeat, fpm_globals.heartbeat);
}

3)对于dynamic方式的子进程,需要定时检查,例如:当空闲的子进程个数小于允许最小的空闲子进程个数时,需要fork;当空闲的子进程个数大于允许的最大的空闲子进程个数时,需要kill掉

/* 1s (in ms) heartbeat for idle server maintenance */
#define FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT (1000)

  即每1S执行一次

  假设当前时间为10:00:00,那么超时时间为10:01:00, 在fpm_event_loop这个无限循环中,当 当前 时间 大于或等于这个超时时间时,会触发fpm_pctl_perform_idle_server_maintenance这个函数,当空闲的子进程个数小于允许最小的空闲子进程个数时,需要fork;当空闲的子进程个数大于允许的最大的空闲子进程个数时,需要kill掉,执行完函数后,假设当前时间为10:05:00,那么下一次超时时间为10:06:00,依次类推 ,参考这里

  建立定时器是在函数fpm_event_loop中的fpm_pctl_perform_idle_server_maintenance_heartbeat(NULL, 0, NULL)

  

void fpm_pctl_perform_idle_server_maintenance_heartbeat(struct fpm_event_s *ev, short which, void *arg) /* {{{ */
{
static struct fpm_event_s heartbeat;
struct timeval now; if (fpm_globals.parent_pid != getpid()) {
return; /* sanity check */
} if (which == FPM_EV_TIMEOUT) {
fpm_clock_get(&now);
if (fpm_pctl_can_spawn_children()) {
fpm_pctl_perform_idle_server_maintenance(&now); /* if it's a child, stop here without creating the next event
* this event is reserved to the master process
*/
if (fpm_globals.is_child) {
return;
}
}
return;
} /* first call without setting which to initialize the timer */
fpm_event_set_timer(&heartbeat, FPM_EV_PERSIST, &fpm_pctl_perform_idle_server_maintenance_heartbeat, NULL);
fpm_event_add(&
heartbeat, FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT);
}

因为是第一次调用 ,所以直接走到倒数第二,第三行, FPM_EV_TIMEOUT 为1

#define FPM_EV_TIMEOUT  (1 << 0)
#define FPM_EV_READ (1 << 1)
#define FPM_EV_PERSIST (1 << 2)
#define FPM_EV_EDGE (1 << 3)
fpm_event_set_timer其实是个宏,
#define fpm_event_set_timer(ev, flags, cb, arg) fpm_event_set((ev), -1, (flags), (cb), (arg))
fpm_event_set中的fd参数传的是-1,因为是定时器,故没有文件描述符,并且调用回调函数
得到现在当前时间,由于是每1分钟执行一次,所以超时时间是当前时间+1分钟
int fpm_event_set(struct fpm_event_s *ev, int fd, int flags, void (*callback)(struct fpm_event_s *, short, void *), void *arg) /* {{{ */
{
if (!ev || !callback || fd < -) {
return -;
}
memset(ev, , sizeof(struct fpm_event_s));
ev->fd = fd;
ev->callback = callback;
ev->arg = arg;
ev->flags = flags;
return ;
}
/* }}} */ int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */
{
struct timeval now;
struct timeval tmp; if (!ev) {
return -;
} ev->index = -; /* it's a triggered event on incoming data */
if (ev->flags & FPM_EV_READ) {
ev->which = FPM_EV_READ;
if (fpm_event_queue_add(&fpm_event_queue_fd, ev) != ) {
return -;
}
return ;
} /* it's a timer event */
ev->which = FPM_EV_TIMEOUT; fpm_clock_get(&now);
if (frequency >= ) {
tmp.tv_sec = frequency / ;
tmp.tv_usec = (frequency % ) * ;
} else {
tmp.tv_sec = ;
tmp.tv_usec = frequency * ;
}
ev->frequency = tmp;
fpm_event_set_timeout(ev, now); //#define fpm_event_set_timeout(ev, now) timeradd(&(now), &(ev)->frequency, &(ev)->timeout); if (fpm_event_queue_add(&fpm_event_queue_timer, ev) != ) {
return -;
} return ;
}

将该定时器放到定时器专属的队列中
static int fpm_event_queue_add(struct fpm_event_queue_s **queue, struct fpm_event_s *ev) /* {{{ */
{
struct fpm_event_queue_s *elt; if (!queue || !ev) {
return -;
} if (fpm_event_queue_isset(*queue, ev)) {
return ;
} if (!(elt = malloc(sizeof(struct fpm_event_queue_s)))) {
zlog(ZLOG_SYSERROR, "Unable to add the event to queue: malloc() failed");
return -;
}
elt->prev = NULL;
elt->next = NULL;
elt->ev = ev; if (*queue) {
(*queue)->prev = elt;
elt->next = *queue;
}
*queue = elt; /* ask the event module to add the fd from its own queue */ //定时器不会走到这里
if (*queue == fpm_event_queue_fd && module->add) {
module->add(ev);
} return ;
}

定时器队列结构体, static struct fpm_event_queue_s *fpm_event_queue_timer = NULL; 是个全局变量

typedef struct fpm_event_queue_s {
struct fpm_event_queue_s *prev;
struct fpm_event_queue_s *next;
struct fpm_event_s *ev;
} fpm_event_queue;

php-fpm定时器的更多相关文章

  1. 纯PHP实现定时器任务(Timer)

    纯PHP实现定时器任务(Timer)   定时器任务,在WEB应用比较常见,如何使用PHP实现定时器任务,大致有两种方案:1)使用Crontab命令,写一个shell脚本,在脚本中调用PHP文件,然后 ...

  2. PHP-max_execution_time与fpm.request_terminate_timeout介绍

    前段时间一位同事跟我说php脚本超时时间以fpm配置优先.经过自己测试后,其实不然,前面的观点只是在某些情况下成立. php脚本超时时间可以在php.ini的max_execution_time和fp ...

  3. Fpm启动机制及流程分析———详细

    FPM(FastCGI Process Manager)是PHP FastCGI运行模式的一个进程管理器,从它的定义可以看出,FPM的核心功能是进程管理,那么它用来管理什么进程呢?这个问题就需要从Fa ...

  4. Objective-C三种定时器CADisplayLink / NSTimer / GCD的使用

    OC中的三种定时器:CADisplayLink.NSTimer.GCD 我们先来看看CADiskplayLink, 点进头文件里面看看, 用注释来说明下 @interface CADisplayLin ...

  5. 微信小程序中利用时间选择器和js无计算实现定时器(将字符串或秒数转换成倒计时)

    转载注明出处 改成了一个单独的js文件,并修改代码增加了通用性,点击这里查看 今天写小程序,有一个需求就是用户选择时间,然后我这边就要开始倒计时. 因为小程序的限制,所以直接选用时间选择器作为选择定时 ...

  6. [Java定时器]用Spring Task实现一个简单的定时器.

    今天做一个项目的的时候需要用到定时器功能.具体需求是: 每个月一号触发一次某个类中的方法去拉取别人的接口获取上一个月份车险过期的用户.如若转载请附上原文链接:http://www.cnblogs.co ...

  7. Node+fs+定时器(node-schedule)+MySql

    目标:将本人写博客时候的截图保存到桌面的图片 执行保存到指定文件进行整理 并写入数据库 先看最终的目录结构: package.json文件: { "name": "zqz ...

  8. 深入理解定时器系列第一篇——理解setTimeout和setInterval

    × 目录 [1]setTimeout [2]setInterval [3]运行机制[4]作用[5]应用 前面的话 很长时间以来,定时器一直是javascript动画的核心技术.但是,关于定时器,人们通 ...

  9. 前端开发:setTimeout与setInterval 定时器与异步循环数组

    前端开发:setTimeout与setInterval 定时器与异步循环数组 前言: 开通博客园三个月以来,随笔记录了工作中遇到的大大小小的难题,也看过无数篇令人启发的文章,我觉得这样的环境是极好的, ...

  10. 转载---javascript 定时器总结

    转载:http://www.jb51.net/article/40193.htm JS里设定延时: 使用SetInterval和设定延时函数setTimeout 很类似.setTimeout 运用在延 ...

随机推荐

  1. Alien::BatToExeConverter 模块应用

    ##  DOS 下批量任务转换成exe二进制可执行文件 Convert a DOS Batch Script to an Executable Alien::BatToExeConverter::ba ...

  2. ApplicationContextAware学习--存疑问题

    先看下ApplicationContextAware的源码:     package org.springframework.context; import org.springframework.b ...

  3. 情感分析snownlp包部分核心代码理解

    snownlps是用Python写的个中文情感分析的包,自带了中文正负情感的训练集,主要是评论的语料库.使用的是朴素贝叶斯原理来训练和预测数据.主要看了一下这个包的几个主要的核心代码,看的过程作了一些 ...

  4. ST3 插件和技巧

    Emmet插件: 快速生成HTML文档结构, 快速编写跨浏览器的CSS并自动帮助你同时编辑, 强大! 语法技巧 简单实用, 值得掌握! SideBar Enhancements插件:  改进了侧边栏, ...

  5. 28. Bad Influence of Western Diet 西式饮食的消极影响

    28. Bad Influence of Western Diet 西式饮食的消极影响 ① The spread of Western eating habits around the world i ...

  6. Initialization of bean failed; nested exception is org.springframework.beans.InvalidPropertyException: Invalid property 'dataSource' of bean class [com.liuyang.jdbc.PersonDao]: No property 'dataSource

    这个错误是说我的启动失败了.这类问题要从配置文件中开始找原因,我用的是spring框架,所以我从application.中找的原因 然后对比路径,对比文件的命名和id,都没有问题,为什么会在启动的时候 ...

  7. Mybatis实现原理探究-实现部分Mybatis功能(上)

    一.前言: MyBatis 是一款优秀的持久层框架,它支持定制化 SQL.存储过程以及高级映射.MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集.MyBatis 可以使用简 ...

  8. @media screen

    参考地址: http://www.swordair.com/blog/2010/08/431/ http://ashaochangfu.blog.163.com/blog/static/1042517 ...

  9. Blender3d做大型项目真实地形快速建模

    https://www.rr-sc.com/thread-16531254-1-1.html Blender3d是一款优秀的动画和建模工具,但在做一些大型建设项目时需要在真实地形上来表现,Blende ...

  10. 高博-《视觉SLAM十四讲》

    0 讲座 (1)SLAM定义 对比雷达传感器和视觉传感器的优缺点(主要介绍视觉SLAM) 单目:不知道尺度信息 双目:知道尺度信息,但测量范围根据预定的基线相关 RGBD:知道深度信息,但是深度信息对 ...