Idle timeout and prototype processes
We utilize unit to effectively scale to zero (spare processes set to 0) when certain applications are not busy.
With 1.26.x, there appears to be prototype processes that run per application. Is there a configuration setting to idle these out as well?
With 1.26 the job of forking new application processes was moved from the unit: controller process to a prototype process for each application.
This scales better for multiple applications and languages. Reduces initialization time for new application processes, enables sharing of opcache for PHP across multiple applications, and enables future memory optimizations.
The prototype is the "application starter" (forking code) and cannot be idled-out without removing the application from the running configuration.
https://github.com/nginx/unit/commit/e207415a78ae67b937faf7e5bcd6e5192993180a
Here is the patch to stop the prototype process when last idle process stopped:
diff --git a/src/nxt_router.c b/src/nxt_router.c
--- a/src/nxt_router.c
+++ b/src/nxt_router.c
@@ -4985,7 +4985,7 @@ nxt_router_adjust_idle_timer(nxt_task_t
{
nxt_app_t *app;
nxt_bool_t queued;
- nxt_port_t *port;
+ nxt_port_t *port, *proto_port;
nxt_msec_t timeout, threshold;
nxt_queue_link_t *lnk;
nxt_event_engine_t *engine;
@@ -5045,12 +5045,35 @@ nxt_router_adjust_idle_timer(nxt_task_t
app->processes--;
port->app = NULL;
+ if (app->port_hash_count == 0) {
+ proto_port = app->proto_port;
+ app->proto_port = NULL;
+ proto_port->app = NULL;
+
+ } else {
+ proto_port = NULL;
+ }
+
nxt_thread_mutex_unlock(&app->mutex);
- nxt_debug(task, "app '%V' send QUIT to idle port %PI",
- &app->name, port->pid);
-
- nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0, NULL);
+ if (proto_port == NULL) {
+ nxt_debug(task, "app '%V' send QUIT to idle port %PI",
+ &app->name, port->pid);
+
+ nxt_port_socket_write(task, port, NXT_PORT_MSG_QUIT, -1, 0, 0,
+ NULL);
+
+ } else {
+ nxt_debug(task, "app '%V' send QUIT to idle proto port %PI",
+ &app->name, proto_port->pid);
+
+ nxt_port_socket_write(task, proto_port, NXT_PORT_MSG_QUIT, -1, 0, 0,
+ NULL);
+
+ nxt_port_close(task, proto_port);
+
+ nxt_port_use(task, proto_port, -1);
+ }
nxt_port_use(task, port, -1);
Be aware about possible racing condition: application process may start processing the request, but not yet acknowledge it to router, at the same time in router application idle timer executed and the process is terminated by router with QUIT message.
Very much appreciated @mar0x ! - I'll give it a shot.