Nginx Time Management
Gettimeofday () overhead
In Linux, Nginx uses gettimeofday () to obtain the current system time;
Gettimeofday is a function provided by the C library (not called by the system). It encapsulates sys_gettimeofday system calls in the kernel.
Linux system calls are implemented through int 80 h, and the system call number is used to distinguish the entry function. The steps are roughly as follows:
1. the API saves the system call number to EAX, and then enters the kernel state through the interrupted call;
2. the interrupt handler function in the kernel calls the corresponding kernel function (System Call) based on the system call number );
3. The system calls the function to save the returned value to EAX and return it to the interrupt processing function;
4. the interrupt processing function is returned to the API;
5. the API returns EAX to the application
However, in addition to basic system calls, x86_64 also provides the sysenter/vsyscall method to obtain kernel-state data. vsyscall creates a kernel-State sharing page in the memory, and the user-state has the right to access it, obtain kernel information without going through system interruptions or falling into the kernel;
Gettimeofday () is a system call through vsyscall.
Update Time Cache
To avoid calling the OS's gettimeofday every time, nginx uses the time cache, and each worker process can be maintained by itself;
To control concurrent access, you need to apply for a lock before each update time cache, And the read time cache does not need to be locked;
To avoid split reads, that is, when a worker process receives interrupted requests during the read time cache process, the time cache is updated by other workers during this period, resulting in inconsistent read time between the front and back ends; nginx introduces the time cache array (a total of 64 members) and updates the next element in the array each time;
The Update Time is implemented through ngx_time_update ().
Typedef struct {
Time_t sec;
Ngx_uint_t msec;
Ngx_int_t gmtoff;
} Ngx_time_t;
Volatile ngx_time_t * ngx_cached_time;
Volatile ngx_str_t ngx_cached_err_log_time;
Volatile ngx_str_t ngx_cached_http_time;
Volatile ngx_str_t ngx_cached_http_log_time;
Volatile ngx_str_t ngx_cached_http_log_iso8601;
Static ngx_time_t cached_time [NGX_TIME_SLOTS];
Static u_char cached_err_log_time [NGX_TIME_SLOTS] [sizeof ("12:00:00")];
Static u_char cached_http_time [NGX_TIME_SLOTS] [sizeof ("Mon, 28 Sep 1970 06:00:00 GMT")];
Static u_char cached_http_log_time [NGX_TIME_SLOTS] [sizeof ("28/Sep/1970: 12: 00: 00 + 0600")];
Static u_char cached_http_log_iso8601 [NGX_TIME_SLOTS] [sizeof ("1970-09-28T12: 00: 00 + 06: 00")];
Static u_char cached_syslog_time [NGX_TIME_SLOTS] [sizeof ("Sep 28 12:00:00")];
Void
Ngx_time_update (void)
{
U_char * p0, * p1, * p2, * p3, * p4;
Ngx_tm_t tm, gmt;
Time_t sec;
Ngx_uint_t msec;
Ngx_time_t * tp;
Struct timeval TV;
If (! Ngx_trylock (& ngx_time_lock) {-- Obtain ngx_time_lock before updating the cache.
Return;
}
Ngx_gettimeofday (& TV); -- macro definition, call the gettimeofday (tp, null) of the OS)
Sec = TV. TV _sec;
Msec = TV. TV _usec/1000;
Ngx_current_msec = (ngx_msec_t) sec * 1000 + msec;
Tp = & cached_time [slot]; -- read the current time Cache
If (tp-> sec = sec) {-- if the cache time is second = current time second, update the msec of the current slot element and return it; otherwise, update the next slot array element;
Tp-> msec = msec;
Ngx_unlock (& ngx_time_lock );
Return;
}
If (slot = NGX_TIME_SLOTS-1 ){
Slot = 0;
} Else {
Slot ++;
}
Tp = & cached_time [slot];
Tp-> sec = sec;
Tp-> msec = msec;
Ngx_gmtime (sec, & gmt );
P0 = & cached_http_time [slot] [0];
-- Ngx_sprintf reads all the parameters and calls ngx_vslprintf. After the subsequent parameters are copied to the memory zone starting with P0 in the format of the second parameter, the value is assigned to cached_http_time [slot,
-- The same applies to the subsequent cached_err_log_time [slot] & cached_http_log_time [slot] & cached_http_log_iso8601 [slot] & cached_syslog_time [slot]
(Void) ngx_sprintf (p0, "% s, % 02d % s % 4d % 02d: % 02d: % 02d GMT ",
Week [gmt. ngx_tm_wday], gmt. ngx_tm_mday,
Months [gmt. ngx_tm_mon-1], gmt. ngx_tm_year,
Gmt. ngx_tm_hour, gmt. ngx_tm_min, gmt. ngx_tm_sec );
..................
Ngx_memory_barrier (); -- disable the compiler from optimizing subsequent statements. Without this restriction, the compiler may merge the first and second parts of the Code, which may cause the interval between these six time updates, during this period, the read time may be inconsistent.
Ngx_cached_time = tp;
Ngx_cached_http_time.data = p0;
Ngx_cached_err_log_time.data = p1;
Ngx_cached_http_log_time.data = p2;
Ngx_cached_http_log_iso8601.data = p3;
Ngx_cached_syslog_time.data = p4;
Ngx_unlock (& ngx_time_lock );
}
The most frequently called ngx_time_update () is when the worker process processes events.
Ngx_worker_process_cycle -- ngx_process_events_and_timers -- ngx_process_events
# Define ngx_process_events ngx_event_actions.process_events
Taking epoll as an example, the corresponding API is ngx_epoll_process_events
Ngx_epoll_process_events (ngx_cycle_t * cycle, ngx_msec_t timer, ngx_uint_t flags)
Events = epoll_wait (ep, event_list, (int) nevents, timer );
Err = (events =-1 )? Ngx_errno: 0;
If (flags & NGX_UPDATE_TIME | ngx_event_timer_alarm ){
Ngx_time_update ();
}
Epoll_wait () can be awakened by three types of events: read/write events, wait time timeout, and event signal interruption.
When epoll_wait () is returned, the time cache is updated and the processing function is called. The event processing function is non-block and its execution time is very short (in milliseconds ), therefore, even if the current time is cached, the error is small and acceptable.
How to control the time update frequency
Nginx provides the timer_resolution parameter to set the cache time update interval;
After this item is configured, nginx will use the interrupt mechanism, instead of using the minimum time in the red/black tree of the timer as the epoll_wait timeout time, that is, the timer will be periodically interrupted.
When the timer_resolution command is used, the epoll_wait timeout value is set to-1, which indicates that epoll_wait will be blocked forever until a read/write event occurs or the signal is interrupted.
Ngx_process_events_and_timers (ngx_cycle_t * cycle)
If (ngx_timer_resolution ){
Timer = NGX_TIMER_INFINITE;
Flags = 0;
} Else {
Timer = ngx_event_find_timer ();
Flags = NGX_UPDATE_TIME;
}
1. When timer_resolution is set, flags = 0. ngx_event_timer_alarm is executed only when epoll_wait () returns ngx_time_update (ngx_event_timer_alarm is set to zero after the update)
2. timer_resolution is not set, flags = NGX_UPDATE_TIME, timer is the minimum timer time in the red/black tree of the timer, and will be used as the timeout time (timeout) of epoll_wait)
Ngx_event_process_init (ngx_cycle_t * cycle)
If (ngx_timer_resolution &&! (Ngx_event_flags & NGX_USE_TIMER_EVENT )){
Ngx_memzero (& sa, sizeof (struct sigaction ));
Sa. sa_handler = ngx_timer_signal_handler;
Sigemptyset (& sa. sa_mask );
If (sigaction (SIGALRM, & sa, NULL) =-1 ){
Ngx_log_error (NGX_LOG_ALERT, cycle-> log, ngx_errno,
"Sigaction (SIGALRM) failed ");
Return NGX_ERROR;
}
Itv. it_interval. TV _sec = ngx_timer_resolution/1000;
Itv. it_interval. TV _usec = (ngx_timer_resolution % 1000) * 1000;
Itv. it_value. TV _sec = ngx_timer_resolution/1000;
Itv. it_value. TV _usec = (ngx_timer_resolution % 1000) * 1000;
If (setitimer (ITIMER_REAL, & itv, NULL) =-1 ){
Ngx_log_error (NGX_LOG_ALERT, cycle-> log, ngx_errno,
"Setitimer () failed ");
}
}
Every ngx_timer_resolution time sends a signal SIGALRM and executes ngx_timer_signal_handler. The latter only uses ngx_event_timer_alarm = 1 for calling ngx_time_update () after epoll_wait () is returned.
-------------------------------------- Split line --------------------------------------
Deployment of Nginx + MySQL + PHP in CentOS 6.2
Build a WEB server using Nginx
Build a Web server based on Linux6.3 + Nginx1.2 + PHP5 + MySQL5.5
Performance Tuning for Nginx in CentOS 6.3
Configure Nginx to load the ngx_pagespeed module in CentOS 6.3
Install and configure Nginx + Pcre + php-fpm in CentOS 6.4
Nginx installation and configuration instructions
Nginx log filtering using ngx_log_if does not record specific logs
-------------------------------------- Split line --------------------------------------
Nginx details: click here
Nginx: click here
This article permanently updates the link address: