summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAntony Dovgal <tony2001@php.net>2009-12-14 14:02:34 +0000
committerAntony Dovgal <tony2001@php.net>2009-12-14 14:02:34 +0000
commit403a58c338232d0d5b72e4c0c807a6c66dcbabf8 (patch)
treef460fd31849ec9abdb13b310637cb606cfd36234
parenta7662039da69b11374529c046006c593df10c630 (diff)
downloadphp-git-403a58c338232d0d5b72e4c0c807a6c66dcbabf8.tar.gz
add experimental dynamic process spawning support (patch by Jerome Loyet)
-rw-r--r--sapi/fpm/fpm/fastcgi.c12
-rw-r--r--sapi/fpm/fpm/fpm_children.c51
-rw-r--r--sapi/fpm/fpm/fpm_children.h2
-rw-r--r--sapi/fpm/fpm/fpm_conf.c60
-rw-r--r--sapi/fpm/fpm/fpm_conf.h10
-rw-r--r--sapi/fpm/fpm/fpm_config.h4
-rw-r--r--sapi/fpm/fpm/fpm_events.c1
-rw-r--r--sapi/fpm/fpm/fpm_process_ctl.c110
-rw-r--r--sapi/fpm/fpm/fpm_process_ctl.h6
-rw-r--r--sapi/fpm/fpm/fpm_request.c15
-rw-r--r--sapi/fpm/fpm/fpm_request.h1
-rw-r--r--sapi/fpm/fpm/fpm_worker_pool.c1
-rw-r--r--sapi/fpm/fpm/fpm_worker_pool.h2
-rw-r--r--sapi/fpm/php-fpm.conf.in20
14 files changed, 251 insertions, 44 deletions
diff --git a/sapi/fpm/fpm/fastcgi.c b/sapi/fpm/fpm/fastcgi.c
index 16153df3c7..4032147982 100644
--- a/sapi/fpm/fpm/fastcgi.c
+++ b/sapi/fpm/fpm/fastcgi.c
@@ -986,13 +986,13 @@ int fcgi_accept_request(fcgi_request *req)
int n = 0;
int allowed = 0;
- while (allowed_clients[n] != INADDR_NONE) {
- if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
- allowed = 1;
- break;
- }
- n++;
+ while (allowed_clients[n] != INADDR_NONE) {
+ if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
+ allowed = 1;
+ break;
}
+ n++;
+ }
if (!allowed) {
fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
closesocket(req->fd);
diff --git a/sapi/fpm/fpm/fpm_children.c b/sapi/fpm/fpm/fpm_children.c
index fe4a2197a9..870acb8962 100644
--- a/sapi/fpm/fpm/fpm_children.c
+++ b/sapi/fpm/fpm/fpm_children.c
@@ -32,8 +32,6 @@
static time_t *last_faults;
static int fault;
-static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop);
-
static void fpm_children_cleanup(int which, void *arg) /* {{{ */
{
free(last_faults);
@@ -180,6 +178,7 @@ void fpm_children_bury() /* {{{ */
while ( (pid = waitpid(-1, &status, WNOHANG | WUNTRACED)) > 0) {
char buf[128];
int severity = ZLOG_NOTICE;
+ int restart_child = 1;
child = fpm_child_find(pid);
@@ -187,6 +186,13 @@ void fpm_children_bury() /* {{{ */
snprintf(buf, sizeof(buf), "with code %d", WEXITSTATUS(status));
+ /* if it's been killed because of dynamic process management
+ * don't restart it automaticaly
+ */
+ if (child && child->idle_kill) {
+ restart_child = 0;
+ }
+
if (WEXITSTATUS(status) != 0) {
severity = ZLOG_WARNING;
}
@@ -201,6 +207,13 @@ void fpm_children_bury() /* {{{ */
snprintf(buf, sizeof(buf), "on signal %d %s%s", WTERMSIG(status), signame, have_core);
+ /* if it's been killed because of dynamic process management
+ * don't restart it automaticaly
+ */
+ if (child && child->idle_kill && WTERMSIG(status) == SIGTERM) {
+ restart_child = 0;
+ }
+
if (WTERMSIG(status) != SIGQUIT) { /* possible request loss */
severity = ZLOG_WARNING;
}
@@ -227,8 +240,11 @@ void fpm_children_bury() /* {{{ */
timersub(&tv1, &child->started, &tv2);
- zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid,
- child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec);
+ if (restart_child) {
+ zlog(ZLOG_STUFF, severity, "child %d (pool %s) exited %s after %ld.%06d seconds from start", (int) pid, child->wp->config->name, buf, tv2.tv_sec, (int) tv2.tv_usec);
+ } else {
+ zlog(ZLOG_STUFF, severity, "child %d (pool %s) has been killed by the process managment after %ld.%06d seconds from start", (int) pid, child->wp->config->name, tv2.tv_sec, (int) tv2.tv_usec);
+ }
fpm_child_close(child, 1 /* in event_loop */);
@@ -254,17 +270,18 @@ void fpm_children_bury() /* {{{ */
if (restart_condition) {
- zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload",
- fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval);
+ zlog(ZLOG_STUFF, ZLOG_WARNING, "failed processes threshold (%d in %d sec) is reached, initiating reload", fpm_global_config.emergency_restart_threshold, fpm_global_config.emergency_restart_interval);
fpm_pctl(FPM_PCTL_STATE_RELOADING, FPM_PCTL_ACTION_SET);
}
}
- fpm_children_make(wp, 1 /* in event loop */);
+ if (restart_child) {
+ fpm_children_make(wp, 1 /* in event loop */, 1);
- if (fpm_globals.is_child) {
- break;
+ if (fpm_globals.is_child) {
+ break;
+ }
}
} else {
zlog(ZLOG_STUFF, ZLOG_ALERT, "oops, unknown child exited %s", buf);
@@ -326,14 +343,24 @@ static void fpm_parent_resources_use(struct fpm_child_s *child) /* {{{ */
}
/* }}} */
-static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop) /* {{{ */
+int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn) /* {{{ */
{
int enough = 0;
pid_t pid;
struct fpm_child_s *child;
+ int max;
- while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < wp->config->pm->max_children) {
+ if (wp->config->pm->style == PM_STYLE_DYNAMIC) {
+ if (!in_event_loop) { /* stating */
+ max = wp->config->pm->dynamic.start_servers;
+ } else {
+ max = wp->running_children + nb_to_spawn;
+ }
+ } else { /* PM_STYLE_STATIC */
+ max = wp->config->pm->max_children;
+ }
+ while (!enough && fpm_pctl_can_spawn_children() && wp->running_children < max) {
child = fpm_resources_prepare(wp);
if (!child) {
@@ -378,7 +405,7 @@ static int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop) /*
int fpm_children_create_initial(struct fpm_worker_pool_s *wp) /* {{{ */
{
- return fpm_children_make(wp, 0 /* not in event loop yet */);
+ return fpm_children_make(wp, 0 /* not in event loop yet */, 0);
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_children.h b/sapi/fpm/fpm/fpm_children.h
index c85adf9298..cf04df245c 100644
--- a/sapi/fpm/fpm/fpm_children.h
+++ b/sapi/fpm/fpm/fpm_children.h
@@ -15,6 +15,7 @@ int fpm_children_create_initial(struct fpm_worker_pool_s *wp);
int fpm_children_free(struct fpm_child_s *child);
void fpm_children_bury();
int fpm_children_init_main();
+int fpm_children_make(struct fpm_worker_pool_s *wp, int in_event_loop, int nb_to_spawn);
struct fpm_child_s;
@@ -27,6 +28,7 @@ struct fpm_child_s {
int fd_stdout, fd_stderr;
void (*tracer)(struct fpm_child_s *);
struct timeval slow_logged;
+ int idle_kill;
pid_t pid;
};
diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c
index d626978f7b..0fa77169ea 100644
--- a/sapi/fpm/fpm/fpm_conf.c
+++ b/sapi/fpm/fpm/fpm_conf.c
@@ -82,8 +82,8 @@ static char *fpm_conf_set_pm_style(void **conf, char *name, void *vv, intptr_t o
if (!strcmp(value, "static")) {
c->style = PM_STYLE_STATIC;
- } else if (!strcmp(value, "apache-like")) {
- c->style = PM_STYLE_APACHE_LIKE;
+ } else if (!strcmp(value, "dynamic")) {
+ c->style = PM_STYLE_DYNAMIC;
} else {
return "invalid value for 'style'";
}
@@ -139,19 +139,19 @@ static char *fpm_conf_set_catch_workers_output(void **conf, char *name, void *vv
}
/* }}} */
-static struct xml_conf_section fpm_conf_set_apache_like_subsection_conf = {
- .path = "apache_like somewhere", /* fixme */
+static struct xml_conf_section fpm_conf_set_dynamic_subsection_conf = {
+ .path = "dynamic somewhere", /* fixme */
.parsers = (struct xml_value_parser []) {
- { XML_CONF_SCALAR, "StartServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.StartServers) },
- { XML_CONF_SCALAR, "MinSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MinSpareServers) },
- { XML_CONF_SCALAR, "MaxSpareServers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, options_apache_like.MaxSpareServers) },
+ { XML_CONF_SCALAR, "start_servers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, dynamic.start_servers) },
+ { XML_CONF_SCALAR, "min_spare_servers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, dynamic.min_spare_servers) },
+ { XML_CONF_SCALAR, "max_spare_servers", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, dynamic.max_spare_servers) },
{ 0, 0, 0, 0 }
}
};
-static char *fpm_conf_set_apache_like_subsection(void **conf, char *name, void *xml_node, intptr_t offset) /* {{{ */
+static char *fpm_conf_set_dynamic_subsection(void **conf, char *name, void *xml_node, intptr_t offset) /* {{{ */
{
- return xml_conf_parse_section(conf, &fpm_conf_set_apache_like_subsection_conf, xml_node);
+ return xml_conf_parse_section(conf, &fpm_conf_set_dynamic_subsection_conf, xml_node);
}
/* }}} */
@@ -191,7 +191,7 @@ static struct xml_conf_section fpm_conf_set_pm_subsection_conf = {
.parsers = (struct xml_value_parser []) {
{ XML_CONF_SCALAR, "style", &fpm_conf_set_pm_style, 0 },
{ XML_CONF_SCALAR, "max_children", &xml_conf_set_slot_integer, offsetof(struct fpm_pm_s, max_children) },
- { XML_CONF_SUBSECTION, "apache_like", &fpm_conf_set_apache_like_subsection, offsetof(struct fpm_pm_s, options_apache_like) },
+ { XML_CONF_SUBSECTION, "dynamic", &fpm_conf_set_dynamic_subsection, offsetof(struct fpm_pm_s, dynamic) },
{ 0, 0, 0, 0 }
}
};
@@ -392,6 +392,46 @@ static int fpm_conf_process_all_pools() /* {{{ */
wp->is_template = 1;
}
+ if (wp->config->pm == NULL) {
+ zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: the process manager is missing (static or dynamic)", wp->config->name);
+ return(-1);
+ }
+
+ if (wp->config->pm->style == PM_STYLE_DYNAMIC) {
+ struct fpm_pm_s *pm = wp->config->pm;
+
+ if (pm->dynamic.min_spare_servers <= 0) {
+ zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: min_spare_servers must be a positive value", wp->config->name);
+ return(-1);
+ }
+
+ if (pm->dynamic.max_spare_servers <= 0) {
+ zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: max_spare_servers must be a positive value", wp->config->name);
+ return(-1);
+ }
+
+ if (pm->dynamic.min_spare_servers > pm->max_children ||
+ pm->dynamic.max_spare_servers > pm->max_children) {
+ zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: min_spare_servers(%d) and max_spare_servers(%d) can't be greater than max_children(%d)",
+ wp->config->name, pm->dynamic.min_spare_servers, pm->dynamic.max_spare_servers, pm->max_children);
+ return(-1);
+ }
+
+ if (pm->dynamic.max_spare_servers < pm->dynamic.min_spare_servers) {
+ zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: max_spare_servers must be greater or equal than min_spare_servers", wp->config->name);
+ return(-1);
+ }
+
+ if (pm->dynamic.start_servers <= 0) {
+ pm->dynamic.start_servers = pm->dynamic.min_spare_servers + ((pm->dynamic.max_spare_servers - pm->dynamic.min_spare_servers) / 2);
+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "pool %s: start_servers has been set to %d", wp->config->name, pm->dynamic.start_servers);
+ } else if (pm->dynamic.start_servers < pm->dynamic.min_spare_servers || pm->dynamic.start_servers > pm->dynamic.max_spare_servers) {
+ zlog(ZLOG_STUFF, ZLOG_ALERT, "pool %s: start_servers must not be less than min_spare_servers and not greaters than max_spare_servers", wp->config->name);
+ return(-1);
+ }
+ }
+
+
if (wp->config->request_slowlog_timeout) {
#if HAVE_FPM_TRACE
if (! (wp->config->slowlog && *wp->config->slowlog)) {
diff --git a/sapi/fpm/fpm/fpm_conf.h b/sapi/fpm/fpm/fpm_conf.h
index 4dd011e5e0..5e6b56c2c3 100644
--- a/sapi/fpm/fpm/fpm_conf.h
+++ b/sapi/fpm/fpm/fpm_conf.h
@@ -28,10 +28,10 @@ struct fpm_pm_s {
int style;
int max_children;
struct {
- int StartServers;
- int MinSpareServers;
- int MaxSpareServers;
- } options_apache_like;
+ int start_servers;
+ int min_spare_servers;
+ int max_spare_servers;
+ } dynamic;
};
struct fpm_listen_options_s {
@@ -62,7 +62,7 @@ struct fpm_worker_pool_config_s {
unsigned catch_workers_output:1;
};
-enum { PM_STYLE_STATIC = 1, PM_STYLE_APACHE_LIKE = 2 };
+enum { PM_STYLE_STATIC = 1, PM_STYLE_DYNAMIC = 2 };
int fpm_conf_init_main();
int fpm_worker_pool_config_free(struct fpm_worker_pool_config_s *wpc);
diff --git a/sapi/fpm/fpm/fpm_config.h b/sapi/fpm/fpm/fpm_config.h
index 6d8a2a603c..165bd7d62d 100644
--- a/sapi/fpm/fpm/fpm_config.h
+++ b/sapi/fpm/fpm/fpm_config.h
@@ -32,6 +32,10 @@
} while (0)
#endif
+#ifndef MIN
+#define MIN(a,b) (((a)<(b))?(a):(b))
+#endif
+
#if defined(HAVE_PTRACE) || defined(PROC_MEM_FILE) || defined(HAVE_MACH_VM_READ)
#define HAVE_FPM_TRACE 1
#else
diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c
index 15db906e72..780dfe9c05 100644
--- a/sapi/fpm/fpm/fpm_events.c
+++ b/sapi/fpm/fpm/fpm_events.c
@@ -100,6 +100,7 @@ int fpm_event_loop() /* {{{ */
event_set(&signal_fd_event, fpm_signals_get_fd(), EV_PERSIST | EV_READ, &fpm_got_signal, 0);
event_add(&signal_fd_event, 0);
fpm_pctl_heartbeat(-1, 0, 0);
+ fpm_pctl_perform_idle_server_maintenance_heartbeat(-1, 0, 0);
zlog(ZLOG_STUFF, ZLOG_NOTICE, "libevent: entering main loop");
event_loop(0);
return 0;
diff --git a/sapi/fpm/fpm/fpm_process_ctl.c b/sapi/fpm/fpm/fpm_process_ctl.c
index 9cecbd3498..4d71ac160c 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.c
+++ b/sapi/fpm/fpm/fpm_process_ctl.c
@@ -307,7 +307,89 @@ static void fpm_pctl_check_request_timeout(struct timeval *now) /* {{{ */
}
}
}
-
+}
+/* }}} */
+
+static void fpm_pctl_perform_idle_server_maintenance(struct timeval *now) /* {{{ */
+{
+ struct fpm_worker_pool_s *wp;
+ struct fpm_child_s *last_idle_child = NULL;
+ int i;
+
+ for (wp = fpm_worker_all_pools; wp; wp = wp->next) {
+ struct fpm_child_s *child;
+ int idle = 0;
+ int active = 0;
+
+ if (wp->config == NULL) continue;
+ if (wp->config->pm->style != PM_STYLE_DYNAMIC) continue;
+
+ for (child = wp->children; child; child = child->next) {
+ int ret = fpm_request_is_idle(child);
+ if (ret == 1) {
+ if (last_idle_child == NULL) {
+ last_idle_child = child;
+ } else {
+ if (child->started.tv_sec < last_idle_child->started.tv_sec) {
+ last_idle_child = child;
+ }
+ }
+ idle++;
+ } else if (ret == 0) {
+ active++;
+ }
+ }
+
+ zlog(ZLOG_STUFF, ZLOG_DEBUG, "[%s] rate=%d idle=%d active=%d total=%d", wp->config->name, wp->idle_spawn_rate, idle, active, wp->running_children);
+
+ if ((active + idle) != wp->running_children) {
+ zlog(ZLOG_STUFF, ZLOG_ERROR, "[%s] unable to retrieve spawning informations", wp->config->name);
+ continue;
+ }
+
+ if (idle > wp->config->pm->dynamic.max_spare_servers && last_idle_child) {
+ last_idle_child->idle_kill = 1;
+ fpm_pctl_kill(last_idle_child->pid, FPM_PCTL_TERM);
+ wp->idle_spawn_rate = 1;
+ continue;
+ }
+
+ if (idle < wp->config->pm->dynamic.min_spare_servers) {
+ if (wp->running_children >= wp->config->pm->max_children) {
+ if (!wp->warn_max_children) {
+ zlog(ZLOG_STUFF, ZLOG_WARNING, "pool %s: server reached max_children setting, consider raising it",
+ wp->config->name);
+ wp->warn_max_children = 1;
+ }
+ wp->idle_spawn_rate = 1;
+ continue;
+ }
+ wp->warn_max_children = 0;
+
+ if (wp->idle_spawn_rate >= 8) {
+ zlog(ZLOG_STUFF, ZLOG_WARNING, "pool %s seems busy (you may need to increase start_servers, or min/max_spare_servers), spawning %d children, there are %d idle, and %d total children", wp->config->name, wp->idle_spawn_rate, idle, wp->running_children);
+ }
+
+ i = MIN(wp->idle_spawn_rate, wp->config->pm->dynamic.min_spare_servers - idle);
+ fpm_children_make(wp, 1, i);
+
+ /* 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;
+ }
+
+ zlog(ZLOG_STUFF, ZLOG_NOTICE, "pool %s: %d child(ren) have been created because of not enough spare children", wp->config->name, i);
+
+ /* Double the spawn rate for the next iteration */
+ if (wp->idle_spawn_rate < FPM_MAX_SPAWN_RATE) {
+ wp->idle_spawn_rate *= 2;
+ }
+ continue;
+ }
+ wp->idle_spawn_rate = 1;
+ }
}
/* }}} */
@@ -328,3 +410,29 @@ void fpm_pctl_heartbeat(int fd, short which, void *arg) /* {{{ */
}
/* }}} */
+void fpm_pctl_perform_idle_server_maintenance_heartbeat(int fd, short which, void *arg) /* {{{ */
+{
+ static struct event heartbeat;
+ struct timeval tv = { .tv_sec = 0, .tv_usec = FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT };
+ struct timeval now;
+
+ if (which == EV_TIMEOUT) {
+ evtimer_del(&heartbeat);
+ 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;
+ }
+ }
+ }
+
+ evtimer_set(&heartbeat, &fpm_pctl_perform_idle_server_maintenance_heartbeat, 0);
+ evtimer_add(&heartbeat, &tv);
+}
+/* }}} */
+
diff --git a/sapi/fpm/fpm/fpm_process_ctl.h b/sapi/fpm/fpm/fpm_process_ctl.h
index 8424f10fe1..23245cc993 100644
--- a/sapi/fpm/fpm/fpm_process_ctl.h
+++ b/sapi/fpm/fpm/fpm_process_ctl.h
@@ -5,12 +5,18 @@
#ifndef FPM_PROCESS_CTL_H
#define FPM_PROCESS_CTL_H 1
+/* spawn max 32 children at once */
+#define FPM_MAX_SPAWN_RATE (32)
+/* 1s (in µs here) heatbeat for idle server maintenance */
+#define FPM_IDLE_SERVER_MAINTENANCE_HEARTBEAT (1000000)
+
struct fpm_child_s;
void fpm_pctl(int new_state, int action);
int fpm_pctl_can_spawn_children();
int fpm_pctl_kill(pid_t pid, int how);
void fpm_pctl_heartbeat(int fd, short which, void *arg);
+void fpm_pctl_perform_idle_server_maintenance_heartbeat(int fd, short which, void *arg);
int fpm_pctl_child_exited();
int fpm_pctl_init_main();
diff --git a/sapi/fpm/fpm/fpm_request.c b/sapi/fpm/fpm/fpm_request.c
index f130792b39..df19f9ce77 100644
--- a/sapi/fpm/fpm/fpm_request.c
+++ b/sapi/fpm/fpm/fpm_request.c
@@ -148,3 +148,18 @@ void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *now,
}
/* }}} */
+int fpm_request_is_idle(struct fpm_child_s *child) /* {{{ */
+{
+ struct fpm_shm_slot_s *slot;
+ struct fpm_shm_slot_s slot_c;
+
+ slot = fpm_shm_slot(child);
+ if (!fpm_shm_slots_acquire(slot, 1)) {
+ return(-1);
+ }
+
+ slot_c = *slot;
+ fpm_shm_slots_release(slot);
+ return(!slot_c.accepted.tv_sec && !slot_c.accepted.tv_usec ? 1 : 0);
+}
+/* }}} */
diff --git a/sapi/fpm/fpm/fpm_request.h b/sapi/fpm/fpm/fpm_request.h
index d768db62b7..7bc9bc8427 100644
--- a/sapi/fpm/fpm/fpm_request.h
+++ b/sapi/fpm/fpm/fpm_request.h
@@ -15,6 +15,7 @@ struct fpm_child_s;
struct timeval;
void fpm_request_check_timed_out(struct fpm_child_s *child, struct timeval *tv, int terminate_timeout, int slowlog_timeout);
+int fpm_request_is_idle(struct fpm_child_s *child);
enum fpm_request_stage_e {
FPM_REQUEST_ACCEPTING = 1,
diff --git a/sapi/fpm/fpm/fpm_worker_pool.c b/sapi/fpm/fpm/fpm_worker_pool.c
index 661200e345..67c15d2c41 100644
--- a/sapi/fpm/fpm/fpm_worker_pool.c
+++ b/sapi/fpm/fpm/fpm_worker_pool.c
@@ -53,6 +53,7 @@ struct fpm_worker_pool_s *fpm_worker_pool_alloc() /* {{{ */
fpm_array_init(&ret->slots_used, sizeof(struct fpm_shm_slot_ptr_s), 50);
fpm_array_init(&ret->slots_free, sizeof(struct fpm_shm_slot_ptr_s), 50);
+ ret->idle_spawn_rate = 1;
return ret;
}
/* }}} */
diff --git a/sapi/fpm/fpm/fpm_worker_pool.h b/sapi/fpm/fpm/fpm_worker_pool.h
index cc0dbbd38d..43654474fc 100644
--- a/sapi/fpm/fpm/fpm_worker_pool.h
+++ b/sapi/fpm/fpm/fpm_worker_pool.h
@@ -35,6 +35,8 @@ struct fpm_worker_pool_s {
/* runtime */
struct fpm_child_s *children;
int running_children;
+ int idle_spawn_rate;
+ int warn_max_children;
};
struct fpm_worker_pool_s *fpm_worker_pool_alloc();
diff --git a/sapi/fpm/php-fpm.conf.in b/sapi/fpm/php-fpm.conf.in
index b637ab84e0..1bbee12f4c 100644
--- a/sapi/fpm/php-fpm.conf.in
+++ b/sapi/fpm/php-fpm.conf.in
@@ -72,29 +72,29 @@
<value name="pm">
Sets style of controling worker process count.
- Valid values are 'static' and 'apache-like'
+ Valid values are 'static' and 'dynamic'
<value name="style">static</value>
Sets the limit on the number of simultaneous requests that will be served.
Equivalent to Apache MaxClients directive.
Equivalent to PHP_FCGI_CHILDREN environment in original php.fcgi
Used with any pm_style.
- <value name="max_children">5</value>
+ <value name="max_children">50</value>
- Settings group for 'apache-like' pm style
- <value name="apache_like">
+ Settings group for 'dynamic' pm style
+ <value name="dynamic">
Sets the number of server processes created on startup.
- Used only when 'apache-like' pm_style is selected
- <value name="StartServers">20</value>
+ Used only when 'dynamic' pm_style is selected
+ <value name="start_servers">20</value>
Sets the desired minimum number of idle server processes.
- Used only when 'apache-like' pm_style is selected
- <value name="MinSpareServers">5</value>
+ Used only when 'dynamic' pm_style is selected
+ <value name="min_spare_servers">5</value>
Sets the desired maximum number of idle server processes.
- Used only when 'apache-like' pm_style is selected
- <value name="MaxSpareServers">35</value>
+ Used only when 'dynamic' pm_style is selected
+ <value name="max_spare_servers">35</value>
</value>