Skip to content

Conversation

@arut
Copy link
Contributor

@arut arut commented Dec 16, 2025

The change allows to reload NGINX configuration in workers by sending SIGURG to the master process, or by using -s update command line option. A dynamic configuration MUST reuse existing listen ports, shared zones, modules, and thread pools.

The dynamic_conf_preload directive is enabled when compiled with -DNGX_DYNAMIC_CONF_PRELOAD and can be used to force configuration reload on worker start. This allows to perform basic testing.

~/nginx-tests$ TEST_NGINX_GLOBALS="dynamic_conf_preload on;" prove .

arut added 6 commits December 11, 2025 15:37
The tree is located in listening objects.  Referencing it from UDP and QUIC
connections allows to transfer the connection to a new listening and keep
receiving UDP packets.
A configuration can now be updated in runtime by sending SIGURG to master
or worker or by using "-s update" command line option.  Configuration
is loaded in a thread and applied after loading.

A dynamic configuration must reuse existing listen ports, shared zones,
modules, and thread pools.
The directive is enabled when the NGX_DYNAMIC_CONF_PRELOAD macro is
defined and non-zero.  It allows to preload a dynamic version of the
static configuration on worker start.  This can be used to test dynamic
configuration reload with existing tests.
@Maryna-f5 Maryna-f5 added this to the nginx-1.29.5 milestone Dec 16, 2025
}

rc = ngx_http_top_request_body_filter(r, out);
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This pattern is repeated so many times, it asks for a small helper function, like ngx_http_call_top_request_body_filter(r, out);.


cmcf = ngx_http_conf_get_module_main_conf(cf, ngx_http_core_module);

cmcf->top_header_filter = ngx_http_top_header_filter;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typically, modules save current top filter into static ngx_http_next_header_filter variable, which still exists outside of cycle.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thread-safe filter chains.

"Per-cycle filter chains"? These were not necessarily thread-unsafe before.

us = uscf->servers->elts;
ous = ouscf->servers->elts;

for (n = 0; n < uscf->servers->nelts; n++) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Missing us++, ous++?

continue;
}

if (ngx_http_upstream_zone_servers_equal(uscf, ouscfp[j])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks suspiciously straightforward. Is it OK to reuse zone with different LB algorithm?


cln->handler = ngx_dynamic_conf_cleanup;
cln->data = ctx;
ctx->count++;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So long-lives connection can hold old config for a while. Perhaps, we can introduce either time limit or limit the number of concurrent cycles, after which we can trigger usual reload.

shm_zone[i].shm.handle = NULL;
#endif
ngx_log_error(NGX_LOG_ERR, cycle->log, 0,
"cannot reuse shared zone \"%V\"",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we fallback to usual reload if in-place reload is not possible?

At least, there could be an option to, say, make existing reload in-place if possible. Incompatible config or too many concurrent cycles could be the triggers for this.


static ngx_command_t ngx_dynamic_conf_commands[] = {

{ ngx_string("dynamic_conf_threads"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think there is a need for more than 1 thread for config reloads. Perhaps, we can introduce dedicated non-configurable pool.

@p-pautov
Copy link
Contributor

This will increase memory consumption, as each worker will have its own config copy. Consolidating all the workers into single process, so that each worker is a thread, could alleviate that. For example, there could be master process and a single worker process with worker threads and if master is disabled it can also become a thread in a single nginx process, in which case the usual reload will become "dynamic".

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants