Nginx Timer Event

Source: Internet
Author: User
Tags event timer

Overview

The implementation of the timer event in Nginx is not related to the kernel. In the event module, when the waiting event cannot arrive within a specified time, the Nginx timeout mechanism is triggered, and the timeout mechanism manages the events that have timed out and handles these timeout events. The management of timed events consists of two aspects: the organization of the timed event object and the time-out detection of the timed event object.

Organization of timed events

The Nginx timer is implemented by the red and black trees. There are three members about time management in the structure of the Save event ngx_event_t , as follows:

struct ngx_event_s{...    /* Flag bit, 1 indicates the current event has timed out */      unsigned         timedout:1;      /* Flag bit, 1 indicates that the current event exists in a timer maintained by the red and black tree */      unsigned         timer_set:1;      /* Timer maintained by red-black tree */      ngx_rbtree_node_t   timer;     ...};

Nginx set two global variables about the timer. Defined in file src/event/ngx_event_timer.c :

/* All timer events composed of red black tree */ngx_thread_volatile ngx_rbtree_t  ngx_event_timer_rbtree;/* red Black Tree Sentinel node */static ngx_rbtree_node_ T          Ngx_event_timer_sentinel;

Each node of this red-black tree represents a member of the event ngx_event_t struct, the timer, and thengx_rbtree_node_t node represents the time-out of the event, The ngx_event_timer_rbtreeof the red-black tree, which is the size of the time-out, represents the most likely time-out event.

Timer event initialization actually invokes the initialization of the red-black tree, which is defined in the file src/event/ngx_event_timer.c :

/* Timer Event initialization */ngx_int_tngx_event_timer_init (ngx_log_t *log) {/    * Initialize Red black tree *    /Ngx_rbtree_init (&ngx_event_ Timer_rbtree, &ngx_event_timer_sentinel,                    ngx_rbtree_insert_timer_value);    /* The following is for multithreaded environments */#if (ngx_threads)    if (Ngx_event_timer_mutex) {        ngx_event_timer_mutex->log = log;        return NGX_OK;    }    Ngx_event_timer_mutex = ngx_mutex_init (log, 0);    if (Ngx_event_timer_mutex = = NULL) {        return ngx_error;    } #endif    return NGX_OK;}
Timeout detection for timed events

When a time-out detection is required for an event, it is only necessary to add the event to the timer red-black tree, which is ngx_event_add_timerby the function and removes an event from the timer red-black tree by the function Ngx_event_del_ Timer implementation. The following functions are defined in the file src/event/ngx_event_timer.h :

/* Remove event from timer */static ngx_inline Voidngx_event_del_timer (ngx_event_t *ev) {ngx_log_debug2 (ngx_log_debug_event, ev- >log, 0, "event Timer del:%d:%M", Ngx_event_ident (ev->data), Ev->timer.key    );    Ngx_mutex_lock (Ngx_event_timer_mutex);    /* Remove the Node object for the specified event from the red-black tree */Ngx_rbtree_delete (&ngx_event_timer_rbtree, &ev->timer);    Ngx_mutex_unlock (Ngx_event_timer_mutex); #if (ngx_debug) ev->timer.left = NULL;    Ev->timer.right = NULL; Ev->timer.parent = NULL; #endif/* Set the corresponding flag bit/ev->timer_set = 0;}    /* Add event to timer */static ngx_inline Voidngx_event_add_timer (ngx_event_t *ev, ngx_msec_t timer) {ngx_msec_t key;    ngx_msec_int_t diff;    /* Set the key value of the event object node */key = ngx_current_msec + timer; /* Determine the appropriate flag bit for the event */if (ev->timer_set) {/* * Use a previous timer value if difference between it and a NEW * value is less than Ngx_timer_lazy_delay milliseconds:this allows * to MinimIze the Rbtree operations for fast connections.        */diff = (ngx_msec_int_t) (Key-ev->timer.key);                           if (Ngx_abs (diff) < Ngx_timer_lazy_delay) {ngx_log_debug3 (ngx_log_debug_event, Ev->log, 0, "Event Timer:%d, old:%M, New:%M", Ngx_event_ident (ev->data), ev->timer.ke            Y, key);        Return    } ngx_del_timer (EV);    } Ev->timer.key = key; Ngx_log_debug3 (ngx_log_debug_event, Ev->log, 0, "EVENT Timer add:%d:%m:%m", ngx_    Event_ident (Ev->data), timer, Ev->timer.key);    Ngx_mutex_lock (Ngx_event_timer_mutex);    /* Insert the event object node into the red-black tree */Ngx_rbtree_insert (&ngx_event_timer_rbtree, &ev->timer);    Ngx_mutex_unlock (Ngx_event_timer_mutex); /* Set Flag bit */Ev->timer_set = 1;}

        Determine if a function timed out by function ngx_event_find_timer Implement, check timer all events are implemented by the function ngx_event_expire_timer . The following functions are defined in the file src/event/ngx_event_timer.c :

/* Find the timer red-black tree leftmost node */ngx_msec_tngx_event_find_timer (void) {ngx_msec_int_t timer;    ngx_rbtree_node_t *node, *root, *sentinel;    /* If the red and black tree is empty */if (ngx_event_timer_rbtree.root = = &ngx_event_timer_sentinel) {return ngx_timer_infinite;    } ngx_mutex_lock (Ngx_event_timer_mutex);    root = Ngx_event_timer_rbtree.root;    Sentinel = Ngx_event_timer_rbtree.sentinel;    /* Find the smallest node of the red and black tree, which is the leftmost node */nodes = Ngx_rbtree_min (root, Sentinel);    Ngx_mutex_unlock (Ngx_event_timer_mutex);    /* Calculates the difference between the leftmost key value and the current time timer, when the timer is greater than 0 means no timeout, no greater than 0 means timeout */timer = (ngx_msec_int_t) (NODE-&GT;KEY-NGX_CURRENT_MSEC);  /* * If the timer is greater than 0, the event does not time out and returns the value; * If the timer is not greater than 0, the event times out, returns 0, the flag triggers a timeout event; */Return (ngx_msec_t) (Timer > 0 Timer: 0);}    /* Check all events in the timer */voidngx_event_expire_timers (void) {ngx_event_t *ev;    ngx_rbtree_node_t *node, *root, *sentinel;    Sentinel = Ngx_event_timer_rbtree.sentinel; /* Loop Check */for (;;)  {Ngx_mutex_lock (Ngx_event_timer_mutex);      root = Ngx_event_timer_rbtree.root;        /* If the timer red black tree is empty, then return directly, do not do any processing */if (root = Sentinel) {return;        }/* Find the leftmost node of the timer red-black tree, which is the smallest node, and also the event object that is most likely to timeout */node = ngx_rbtree_min (root, Sentinel); /* Node->key <= ngx_current_time */* If the current event checked has timed out */if ((ngx_msec_int_t) (Node->key-ngx_curren T_MSEC) <= 0) {/* Gets timeout specific event */EV = (ngx_event_t *) ((char *) node-offsetof (ngx_event_t, Timer            ));                 /* The following is for multithreading */#if (ngx_threads) if (ngx_threaded && ngx_trylock (ev->lock) = = 0) {/*  * We cannot change the timer of the event which is being * handled by another thread.                 And we cannot easy walk * the Rbtree to find next expired timer so we exit the loop.                 * However, it should was a rare case when the event was * being handled had an expired timer.            */    NGX_LOG_DEBUG1 (ngx_log_debug_event, Ev->log, 0, "EVENT%p is busy in expire timers",                EV);            Break                            } #endif ngx_log_debug2 (ngx_log_debug_event, Ev->log, 0, "EVENT Timer del:%d:%M",            Ngx_event_ident (Ev->data), Ev->timer.key);            /* Remove the timed-out event object from the existing timer red-black tree */Ngx_rbtree_delete (&ngx_event_timer_rbtree, &ev->timer);            Ngx_mutex_unlock (Ngx_event_timer_mutex); #if (ngx_debug) ev->timer.left = NULL;            Ev->timer.right = NULL;            Ev->timer.parent = NULL; #endif/* Set the monitor flag bit of the event in the timer red-black tree */Ev->timer_set = 0;/* 0 means not monitored */                /* Multithreaded Environment */#if (ngx_threads) if (ngx_threaded) {ev->posted_timedout = 1;                Ngx_post_event (EV, &ngx_posted_events);                Ngx_unlock (Ev->lock);            Continue } #endif            /* Set the time-out flag bit for the event */ev->timedout = 1;/* 1 indicates that the event has timed out */* called the handler for the timed-out event * *            Ev->handler (EV);        Continue    } break; } ngx_mutex_unlock (Ngx_event_timer_mutex);}

Resources

"Deep analysis of Nginx"

"Deep understanding of Nginx"

Nginx Timer Event

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.