php-fpm定時器

php-fpm有三種定時器php

1)主進程接收到用戶的信號,例如sigusr,主進程執行kill(子進程號,sigquit),的同時,設置定時器,在一個無限循環裏若是當前時間 大於或等於 該定時器的過時時間,則主進程執行kill(子進程號,sigterm);數據庫

2)對於在php-fpm裏設置了request_terminate_timeout 和request_slowlog_timeout函數

  注:set_time_limit()和max_execution_time隻影響腳本自己執行的時間。php-fpm

  (這兩個參數在php.ini中)任何發生在諸如使用system()的系統調用,流操做,數據庫操做等的腳本執行的最大時間不包括其中.oop

  創建定時器是在函數fpm_event_loop中的fpm_pctl_heartbeat函數,調用前有個判斷條件 fpm_globals.heartbeat須要大於0ui

在解析php-fpm.conf文件中,fpm_globals.heartbeat最終爲request_terminate_timeout和request_slowlog_timeout較小的一個this

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 * 1000) / 3) : (wp->config->request_terminate_timeout * 1000) / 3;
    }

    if (wp->config->request_slowlog_timeout) {
        fpm_globals.heartbeat = fpm_globals.heartbeat ? MIN(fpm_globals.heartbeat, (wp->config->request_slowlog_timeout * 1000) / 3) : (wp->config->request_slowlog_timeout * 1000) / 3;

    }  
}

 

 

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

#define FPM_PCTL_MIN_HEARTBEAT (130).net

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掉code

/* 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 < -1) {
        return -1;
    }
    memset(ev, 0, sizeof(struct fpm_event_s));
    ev->fd = fd;
    ev->callback = callback;
    ev->arg = arg;
    ev->flags = flags;
    return 0;
}
/* }}} */

int fpm_event_add(struct fpm_event_s *ev, unsigned long int frequency) /* {{{ */
{
    struct timeval now;
    struct timeval tmp;

    if (!ev) {
        return -1;
    }

    ev->index = -1;

    /* 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) != 0) {
            return -1;
        }
        return 0;
    }

    /* it's a timer event */
    ev->which = FPM_EV_TIMEOUT;

    fpm_clock_get(&now);
    if (frequency >= 1000) {
        tmp.tv_sec = frequency / 1000;
        tmp.tv_usec = (frequency % 1000) * 1000;
    } else {
        tmp.tv_sec = 0;
        tmp.tv_usec = frequency * 1000;
    }
    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) != 0) {
        return -1;
    }

    return 0;
}
 

 


將該定時器放到定時器專屬的隊列中

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 -1;
    }

    if (fpm_event_queue_isset(*queue, ev)) {
        return 0;
    }

    if (!(elt = malloc(sizeof(struct fpm_event_queue_s)))) {
        zlog(ZLOG_SYSERROR, "Unable to add the event to queue: malloc() failed");
        return -1;
    }
    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 0;    
}
 

定時器隊列結構體, 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;
相關文章
相關標籤/搜索