Skip to content

Commit

Permalink
Introducing extended app process management.
Browse files Browse the repository at this point in the history
- Pre-fork 'processes.spare' application processes;
- fork more processes to keep 'processes.spare' idle processes;
- fork on-demand up to 'processes.max' count;
- scale down idle application processes above 'processes.spare' after
  'processes.idle_timeout';
- number of concurrently started application processes also limited by
  'processes.spare' (or 1, if spare is 0).
  • Loading branch information
mar0x committed Jan 29, 2018
1 parent a36babd commit 9cd4fdb
Show file tree
Hide file tree
Showing 16 changed files with 982 additions and 137 deletions.
2 changes: 0 additions & 2 deletions src/nxt_application.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,6 @@ struct nxt_common_app_conf_s {

char *working_directory;

uint32_t workers;

union {
nxt_python_app_conf_t python;
nxt_php_app_conf_t php;
Expand Down
7 changes: 7 additions & 0 deletions src/nxt_conf.c
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,13 @@ nxt_conf_get_string(nxt_conf_value_t *value, nxt_str_t *str)
}


int64_t
nxt_conf_get_integer(nxt_conf_value_t *value)
{
return value->u.integer;
}


nxt_uint_t
nxt_conf_object_members_count(nxt_conf_value_t *value)
{
Expand Down
1 change: 1 addition & 0 deletions src/nxt_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ void nxt_conf_json_position(u_char *start, u_char *pos, nxt_uint_t *line,
nxt_int_t nxt_conf_validate(nxt_conf_validation_t *vldt);

void nxt_conf_get_string(nxt_conf_value_t *value, nxt_str_t *str);
int64_t nxt_conf_get_integer(nxt_conf_value_t *value);

// FIXME reimplement and reorder functions below
nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value);
Expand Down
143 changes: 139 additions & 4 deletions src/nxt_conf_validation.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ static nxt_int_t nxt_conf_vldt_app(nxt_conf_validation_t *vldt,
nxt_str_t *name, nxt_conf_value_t *value);
static nxt_int_t nxt_conf_vldt_object(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
static nxt_int_t nxt_conf_vldt_processes(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
static nxt_int_t nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data);
static nxt_int_t nxt_conf_vldt_system(nxt_conf_validation_t *vldt,
Expand Down Expand Up @@ -107,22 +109,42 @@ static nxt_conf_vldt_object_t nxt_conf_vldt_app_limits_members[] = {
};


static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = {
{ nxt_string("type"),
NXT_CONF_VLDT_STRING,
static nxt_conf_vldt_object_t nxt_conf_vldt_app_processes_members[] = {
{ nxt_string("spare"),
NXT_CONF_VLDT_INTEGER,
NULL,
NULL },

{ nxt_string("max"),
NXT_CONF_VLDT_INTEGER,
NULL,
NULL },

{ nxt_string("workers"),
{ nxt_string("idle_timeout"),
NXT_CONF_VLDT_INTEGER,
NULL,
NULL },

NXT_CONF_VLDT_END
};


static nxt_conf_vldt_object_t nxt_conf_vldt_common_members[] = {
{ nxt_string("type"),
NXT_CONF_VLDT_STRING,
NULL,
NULL },

{ nxt_string("limits"),
NXT_CONF_VLDT_OBJECT,
&nxt_conf_vldt_object,
(void *) &nxt_conf_vldt_app_limits_members },

{ nxt_string("processes"),
NXT_CONF_VLDT_INTEGER | NXT_CONF_VLDT_OBJECT,
&nxt_conf_vldt_processes,
(void *) &nxt_conf_vldt_app_processes_members },

{ nxt_string("user"),
NXT_CONF_VLDT_STRING,
nxt_conf_vldt_system,
Expand Down Expand Up @@ -475,6 +497,119 @@ nxt_conf_vldt_object(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
}


typedef struct {
int64_t spare;
int64_t max;
int64_t idle_timeout;
} nxt_conf_vldt_processes_conf_t;


static nxt_conf_map_t nxt_conf_vldt_processes_conf_map[] = {
{
nxt_string("spare"),
NXT_CONF_MAP_INT64,
offsetof(nxt_conf_vldt_processes_conf_t, spare),
},

{
nxt_string("max"),
NXT_CONF_MAP_INT64,
offsetof(nxt_conf_vldt_processes_conf_t, max),
},

{
nxt_string("idle_timeout"),
NXT_CONF_MAP_INT64,
offsetof(nxt_conf_vldt_processes_conf_t, idle_timeout),
},
};


static nxt_int_t
nxt_conf_vldt_processes(nxt_conf_validation_t *vldt, nxt_conf_value_t *value,
void *data)
{
int64_t int_value;
nxt_int_t ret;
nxt_conf_vldt_processes_conf_t proc;

static nxt_str_t max_str = nxt_string("max");

if (nxt_conf_type(value) == NXT_CONF_INTEGER) {
int_value = nxt_conf_get_integer(value);

if (int_value < 1) {
return nxt_conf_vldt_error(vldt, "The \"processes\" number must be "
"equal to or greater than 1.");
}

if (int_value > NXT_INT32_T_MAX) {
return nxt_conf_vldt_error(vldt, "The \"processes\" number must "
"not exceed %d.", NXT_INT32_T_MAX);
}

return NXT_OK;
}

ret = nxt_conf_vldt_object(vldt, value, data);
if (ret != NXT_OK) {
return ret;
}

proc.spare = 1;
proc.max = 1;
proc.idle_timeout = 15;

ret = nxt_conf_map_object(vldt->pool, value,
nxt_conf_vldt_processes_conf_map,
nxt_nitems(nxt_conf_vldt_processes_conf_map),
&proc);
if (ret != NXT_OK) {
return ret;
}

if (proc.spare < 0) {
return nxt_conf_vldt_error(vldt, "The \"spare\" number must not be "
"negative.");
}

if (proc.spare > NXT_INT32_T_MAX) {
return nxt_conf_vldt_error(vldt, "The \"spare\" number must not "
"not exceed %d.", NXT_INT32_T_MAX);
}

if (nxt_conf_get_object_member(value, &max_str, NULL) != NULL) {

if (proc.max < 1) {
return nxt_conf_vldt_error(vldt, "The \"max\" number must be equal "
"to or greater than 1.");
}

if (proc.max > NXT_INT32_T_MAX) {
return nxt_conf_vldt_error(vldt, "The \"max\" number must not "
"not exceed %d.", NXT_INT32_T_MAX);
}

if (proc.max < proc.spare) {
return nxt_conf_vldt_error(vldt, "The \"spare\" number must be "
"lower than \"max\".");
}
}

if (proc.idle_timeout < 0) {
return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
"be negative.");
}

if (proc.idle_timeout > NXT_INT32_T_MAX / 1000) {
return nxt_conf_vldt_error(vldt, "The \"idle_timeout\" number must not "
"not exceed %d.", NXT_INT32_T_MAX / 1000);
}

return NXT_OK;
}


static nxt_int_t
nxt_conf_vldt_object_iterator(nxt_conf_validation_t *vldt,
nxt_conf_value_t *value, void *data)
Expand Down
6 changes: 0 additions & 6 deletions src/nxt_main_process.c
Original file line number Diff line number Diff line change
Expand Up @@ -114,12 +114,6 @@ static nxt_conf_map_t nxt_common_app_conf[] = {
offsetof(nxt_common_app_conf_t, working_directory),
},

{
nxt_string("workers"),
NXT_CONF_MAP_INT32,
offsetof(nxt_common_app_conf_t, workers),
},

{
nxt_string("home"),
NXT_CONF_MAP_CSTRZ,
Expand Down
1 change: 1 addition & 0 deletions src/nxt_port.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ nxt_port_mp_cleanup(nxt_task_t *task, void *obj, void *data)

nxt_assert(port->use_count == 0);
nxt_assert(port->app_link.next == NULL);
nxt_assert(port->idle_link.next == NULL);

nxt_assert(nxt_queue_is_empty(&port->messages));
nxt_assert(nxt_lvlhsh_is_empty(&port->rpc_streams));
Expand Down
3 changes: 3 additions & 0 deletions src/nxt_port.h
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,9 @@ struct nxt_port_s {
nxt_queue_link_t app_link; /* for nxt_app_t.ports */
nxt_app_t *app;

nxt_queue_link_t idle_link; /* for nxt_app_t.idle_ports */
nxt_msec_t idle_start;

nxt_queue_t messages; /* of nxt_port_send_msg_t */
nxt_thread_mutex_t write_mutex;

Expand Down
Loading

0 comments on commit 9cd4fdb

Please sign in to comment.