Introduced worker_shutdown_timeout.

The directive configures a timeout to be used when gracefully shutting down
worker processes.  When the timer expires, nginx will try to close all
the connections currently open to facilitate shutdown.
This commit is contained in:
Maxim Dounin 2017-03-07 18:51:16 +03:00
parent 1a58418ae7
commit 12b9974d51
5 changed files with 66 additions and 0 deletions

View File

@ -124,6 +124,13 @@ static ngx_command_t ngx_core_commands[] = {
offsetof(ngx_core_conf_t, rlimit_core),
NULL },
{ ngx_string("worker_shutdown_timeout"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
0,
offsetof(ngx_core_conf_t, shutdown_timeout),
NULL },
{ ngx_string("working_directory"),
NGX_MAIN_CONF|NGX_DIRECT_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_slot,
@ -1014,6 +1021,7 @@ ngx_core_module_create_conf(ngx_cycle_t *cycle)
ccf->daemon = NGX_CONF_UNSET;
ccf->master = NGX_CONF_UNSET;
ccf->timer_resolution = NGX_CONF_UNSET_MSEC;
ccf->shutdown_timeout = NGX_CONF_UNSET_MSEC;
ccf->worker_processes = NGX_CONF_UNSET;
ccf->debug_points = NGX_CONF_UNSET;
@ -1042,6 +1050,7 @@ ngx_core_module_init_conf(ngx_cycle_t *cycle, void *conf)
ngx_conf_init_value(ccf->daemon, 1);
ngx_conf_init_value(ccf->master, 1);
ngx_conf_init_msec_value(ccf->timer_resolution, 0);
ngx_conf_init_msec_value(ccf->shutdown_timeout, 0);
ngx_conf_init_value(ccf->worker_processes, 1);
ngx_conf_init_value(ccf->debug_points, 0);

View File

@ -15,6 +15,7 @@ static ngx_int_t ngx_init_zone_pool(ngx_cycle_t *cycle,
ngx_shm_zone_t *shm_zone);
static ngx_int_t ngx_test_lockfile(u_char *file, ngx_log_t *log);
static void ngx_clean_old_cycles(ngx_event_t *ev);
static void ngx_shutdown_timer_handler(ngx_event_t *ev);
volatile ngx_cycle_t *ngx_cycle;
@ -22,6 +23,7 @@ ngx_array_t ngx_old_cycles;
static ngx_pool_t *ngx_temp_pool;
static ngx_event_t ngx_cleaner_event;
static ngx_event_t ngx_shutdown_event;
ngx_uint_t ngx_test_config;
ngx_uint_t ngx_dump_config;
@ -1333,3 +1335,54 @@ ngx_clean_old_cycles(ngx_event_t *ev)
ngx_old_cycles.nelts = 0;
}
}
void
ngx_set_shutdown_timer(ngx_cycle_t *cycle)
{
ngx_core_conf_t *ccf;
ccf = (ngx_core_conf_t *) ngx_get_conf(cycle->conf_ctx, ngx_core_module);
if (ccf->shutdown_timeout) {
ngx_shutdown_event.handler = ngx_shutdown_timer_handler;
ngx_shutdown_event.data = cycle;
ngx_shutdown_event.log = cycle->log;
ngx_shutdown_event.cancelable = 1;
ngx_add_timer(&ngx_shutdown_event, ccf->shutdown_timeout);
}
}
static void
ngx_shutdown_timer_handler(ngx_event_t *ev)
{
ngx_uint_t i;
ngx_cycle_t *cycle;
ngx_connection_t *c;
cycle = ev->data;
c = cycle->connections;
for (i = 0; i < cycle->connection_n; i++) {
if (c[i].fd == (ngx_socket_t) -1
|| c[i].read == NULL
|| c[i].read->accept
|| c[i].read->channel
|| c[i].read->resolver)
{
continue;
}
ngx_log_debug1(NGX_LOG_DEBUG_CORE, ev->log, 0,
"*%uA shutdown timeout", c[i].number);
c[i].close = 1;
c[i].error = 1;
c[i].read->handler(c[i].read);
}
}

View File

@ -88,6 +88,7 @@ typedef struct {
ngx_flag_t master;
ngx_msec_t timer_resolution;
ngx_msec_t shutdown_timeout;
ngx_int_t worker_processes;
ngx_int_t debug_points;
@ -129,6 +130,7 @@ ngx_pid_t ngx_exec_new_binary(ngx_cycle_t *cycle, char *const *argv);
ngx_cpuset_t *ngx_get_cpu_affinity(ngx_uint_t n);
ngx_shm_zone_t *ngx_shared_memory_add(ngx_conf_t *cf, ngx_str_t *name,
size_t size, void *tag);
void ngx_set_shutdown_timer(ngx_cycle_t *cycle);
extern volatile ngx_cycle_t *ngx_cycle;

View File

@ -763,6 +763,7 @@ ngx_worker_process_cycle(ngx_cycle_t *cycle, void *data)
if (!ngx_exiting) {
ngx_exiting = 1;
ngx_set_shutdown_timer(cycle);
ngx_close_listening_sockets(cycle);
ngx_close_idle_connections(cycle);
}

View File

@ -800,6 +800,7 @@ ngx_worker_thread(void *data)
if (!ngx_exiting) {
ngx_exiting = 1;
ngx_set_shutdown_timer(cycle);
ngx_close_listening_sockets(cycle);
ngx_close_idle_connections(cycle);
}