From 97216b657e7b0cd578ef392077561eb21d2dc99d Mon Sep 17 00:00:00 2001 From: Rohit Joshi Date: Tue, 14 Jun 2016 20:05:31 -0400 Subject: [PATCH 1/6] Replacing default DNS check from 1000 ms to TTL value Replacing hardcoded 1000 ms to refresh_in which is derived based on TTL or default 1000 --- ngx_http_upstream_dynamic_servers.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ngx_http_upstream_dynamic_servers.c b/ngx_http_upstream_dynamic_servers.c index 05b2889..86daeb9 100644 --- a/ngx_http_upstream_dynamic_servers.c +++ b/ngx_http_upstream_dynamic_servers.c @@ -558,7 +558,7 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t return; } - ngx_add_timer(&dynamic_server->timer, 1000); + ngx_add_timer(&dynamic_server->timer, refresh_in); } // Copied from src/core/ngx_resolver.c (nginx version 1.7.7). From a4018cc2745906f969681e3f017d72b75d289f23 Mon Sep 17 00:00:00 2001 From: Rohit Joshi Date: Tue, 14 Jun 2016 20:08:36 -0400 Subject: [PATCH 2/6] Update ngx_http_upstream_dynamic_servers.c --- ngx_http_upstream_dynamic_servers.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ngx_http_upstream_dynamic_servers.c b/ngx_http_upstream_dynamic_servers.c index 86daeb9..e1b1ccd 100644 --- a/ngx_http_upstream_dynamic_servers.c +++ b/ngx_http_upstream_dynamic_servers.c @@ -533,11 +533,10 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t dynamic_server->pool = new_pool; end: - + uint32_t refresh_in = 1000; if (ctx->resolver->log->log_level & NGX_LOG_DEBUG_CORE) { hash = ngx_crc32_short(ctx->name.data, ctx->name.len); rn = ngx_resolver_lookup_name(ctx->resolver, &ctx->name, hash); - uint32_t refresh_in; if (rn != NULL && rn->ttl) { refresh_in = (rn->valid - ngx_time()) * 1000; From a3d7c972a7c5fc67d879a15c013987e9a9e4b024 Mon Sep 17 00:00:00 2001 From: ytr289 Date: Tue, 14 Jun 2016 22:52:02 -0400 Subject: [PATCH 3/6] defaulting refresh time to 10s + fixed integer overflow --- ngx_http_upstream_dynamic_servers.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/ngx_http_upstream_dynamic_servers.c b/ngx_http_upstream_dynamic_servers.c index e1b1ccd..c63db26 100644 --- a/ngx_http_upstream_dynamic_servers.c +++ b/ngx_http_upstream_dynamic_servers.c @@ -392,7 +392,7 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t ngx_http_upstream_dynamic_server_main_conf_t *udsmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, ngx_http_upstream_dynamic_servers_module); ngx_http_upstream_dynamic_server_conf_t *dynamic_server; ngx_conf_t cf; - uint32_t hash; + uint32_t hash, refresh_in; ngx_resolver_node_t *rn; ngx_pool_t *new_pool; ngx_addr_t *addrs; @@ -533,18 +533,15 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t dynamic_server->pool = new_pool; end: - uint32_t refresh_in = 1000; + refresh_in = 10000; if (ctx->resolver->log->log_level & NGX_LOG_DEBUG_CORE) { hash = ngx_crc32_short(ctx->name.data, ctx->name.len); rn = ngx_resolver_lookup_name(ctx->resolver, &ctx->name, hash); if (rn != NULL && rn->ttl) { - refresh_in = (rn->valid - ngx_time()) * 1000; - - if (!refresh_in || refresh_in < 1000) { - refresh_in = 1000; + int32_t rin = rn->valid - ngx_time(); + if ( rin > 0) { + refresh_in = rin * 1000; } - } else { - refresh_in = 1000; } ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Refreshing DNS of '%V' in %ims", &ctx->name, refresh_in); From 4d061f788c4c4899c1078a20e08847071fca2a50 Mon Sep 17 00:00:00 2001 From: Rohit Joshi Date: Fri, 1 Jul 2016 13:31:45 -0400 Subject: [PATCH 4/6] Added support for resolve with refresh_in time Added support for optional debug_log per dynamic upstream --- ngx_http_upstream_dynamic_servers.c | 51 +++++++++++++++++++++++------ 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/ngx_http_upstream_dynamic_servers.c b/ngx_http_upstream_dynamic_servers.c index c63db26..9e25373 100644 --- a/ngx_http_upstream_dynamic_servers.c +++ b/ngx_http_upstream_dynamic_servers.c @@ -15,6 +15,8 @@ typedef struct { ngx_str_t host; in_port_t port; ngx_event_t timer; + ngx_uint_t refresh_in; + ngx_uint_t debug_log; } ngx_http_upstream_dynamic_server_conf_t; typedef struct { @@ -193,10 +195,14 @@ static char * ngx_http_upstream_dynamic_server_directive(ngx_conf_t *cf, ngx_com } // BEGIN CUSTOMIZATION: differs from default "server" implementation - if (ngx_strcmp(value[i].data, "resolve") == 0) { + if ((ngx_strcmp(value[i].data, "resolve") == 0) || (ngx_strncmp(value[i].data, "resolve=", 8) == 0)){ // Determine if the server given is an IP address or a hostname by running // through ngx_parse_url with no_resolve enabled. Only if a hostname is given // will we add this to the list of dynamic servers that we will resolve again. + ngx_uint_t refresh_in = 10000; + if (ngx_strncmp(value[i].data, "resolve=", 8) == 0) { + refresh_in = ngx_atoi(&value[i].data[8], value[i].len - 8); + } ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; @@ -215,10 +221,21 @@ static char * ngx_http_upstream_dynamic_server_directive(ngx_conf_t *cf, ngx_com dynamic_server->host = u.host; dynamic_server->port = (in_port_t) (u.no_port ? u.default_port : u.port); + dynamic_server->refresh_in = refresh_in; + dynamic_server->debug_log = 0; + } continue; } + + if (ngx_strcmp(value[i].data, "debug_log") == 0) { + // enable debug log. this must be followed by resolve + if (dynamic_server) { + dynamic_server->debug_log = 1; + } + continue; + } // END CUSTOMIZATION goto invalid; @@ -381,7 +398,9 @@ static void ngx_http_upstream_dynamic_server_resolve(ngx_event_t *ev) { ctx->data = dynamic_server; ctx->timeout = udsmcf->resolver_timeout; - ngx_log_debug(NGX_LOG_DEBUG_CORE, ev->log, 0, "upstream-dynamic-servers: Resolving '%V'", &ctx->name); + if(dynamic_server && dynamic_server->debug_log) { + ngx_log_debug(NGX_LOG_DEBUG_CORE, ev->log, 0, "upstream-dynamic-servers: Resolving '%V'", &ctx->name); + } if (ngx_resolve_name(ctx) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, ev->log, 0, "upstream-dynamic-servers: ngx_resolve_name failed for '%V'", &ctx->name); ngx_add_timer(&dynamic_server->timer, 1000); @@ -392,14 +411,16 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t ngx_http_upstream_dynamic_server_main_conf_t *udsmcf = ngx_http_cycle_get_module_main_conf(ngx_cycle, ngx_http_upstream_dynamic_servers_module); ngx_http_upstream_dynamic_server_conf_t *dynamic_server; ngx_conf_t cf; - uint32_t hash, refresh_in; ngx_resolver_node_t *rn; ngx_pool_t *new_pool; ngx_addr_t *addrs; + ngx_uint_t refresh_in = 10000; dynamic_server = ctx->data; - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Finished resolving '%V'", &ctx->name); + if(dynamic_server && dynamic_server->debug_log) { + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Finished resolving '%V'", &ctx->name); + } if (ctx->state) { ngx_log_error(NGX_LOG_ERR, ctx->resolver->log, 0, "upstream-dynamic-servers: '%V' could not be resolved (%i: %s)", &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); @@ -451,7 +472,9 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t } } - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: No DNS changes for '%V' - keeping existing upstream configuration", &ctx->name); + if(dynamic_server && dynamic_server->debug_log) { + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: No DNS changes for '%V' - keeping existing upstream configuration", &ctx->name); + } goto end; reinit_upstream: @@ -462,7 +485,9 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t goto end; } - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: DNS changes for '%V' detected - reinitializing upstream configuration", &ctx->name); + if(dynamic_server && dynamic_server->debug_log) { + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: DNS changes for '%V' detected - reinitializing upstream configuration", &ctx->name); + } ngx_memzero(&cf, sizeof(ngx_conf_t)); cf.name = "dynamic_server_init_upstream"; @@ -509,7 +534,9 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1); addr->name.len = len; addr->name.data = p; - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: '%V' was resolved to '%V'", &ctx->name, &addr->name); + if(dynamic_server && dynamic_server->debug_log) { + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: '%V' was resolved to '%V'", &ctx->name, &addr->name); + } } // If the domain failed to resolve, mark this server as down. @@ -533,9 +560,11 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t dynamic_server->pool = new_pool; end: - refresh_in = 10000; + if(dynamic_server) { + refresh_in = dynamic_server->refresh_in; + } if (ctx->resolver->log->log_level & NGX_LOG_DEBUG_CORE) { - hash = ngx_crc32_short(ctx->name.data, ctx->name.len); + uint32_t hash = ngx_crc32_short(ctx->name.data, ctx->name.len); rn = ngx_resolver_lookup_name(ctx->resolver, &ctx->name, hash); if (rn != NULL && rn->ttl) { int32_t rin = rn->valid - ngx_time(); @@ -544,7 +573,9 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t } } - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Refreshing DNS of '%V' in %ims", &ctx->name, refresh_in); + if(dynamic_server && dynamic_server->debug_log) { + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Refreshing DNS of '%V' in %ims", &ctx->name, refresh_in); + } } ngx_resolve_name_done(ctx); From f42533ab553d30026ba7afe350ccc5dae78e4ef5 Mon Sep 17 00:00:00 2001 From: Rohit Joshi Date: Thu, 7 Jul 2016 15:40:38 -0400 Subject: [PATCH 5/6] Added support for refresh_interval Removed debug_log --- ngx_http_upstream_dynamic_servers.c | 57 ++++++++++++----------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/ngx_http_upstream_dynamic_servers.c b/ngx_http_upstream_dynamic_servers.c index 9e25373..396d76a 100644 --- a/ngx_http_upstream_dynamic_servers.c +++ b/ngx_http_upstream_dynamic_servers.c @@ -16,7 +16,6 @@ typedef struct { in_port_t port; ngx_event_t timer; ngx_uint_t refresh_in; - ngx_uint_t debug_log; } ngx_http_upstream_dynamic_server_conf_t; typedef struct { @@ -98,6 +97,8 @@ static char * ngx_http_upstream_dynamic_server_directive(ngx_conf_t *cf, ngx_com ngx_int_t weight, max_fails; ngx_uint_t i; ngx_http_upstream_server_t *us; + + #if nginx_version <= 1007002 if (uscf->servers == NULL) { @@ -195,15 +196,11 @@ static char * ngx_http_upstream_dynamic_server_directive(ngx_conf_t *cf, ngx_com } // BEGIN CUSTOMIZATION: differs from default "server" implementation - if ((ngx_strcmp(value[i].data, "resolve") == 0) || (ngx_strncmp(value[i].data, "resolve=", 8) == 0)){ + if (ngx_strcmp(value[i].data, "resolve") == 0){ // Determine if the server given is an IP address or a hostname by running // through ngx_parse_url with no_resolve enabled. Only if a hostname is given // will we add this to the list of dynamic servers that we will resolve again. - ngx_uint_t refresh_in = 10000; - if (ngx_strncmp(value[i].data, "resolve=", 8) == 0) { - refresh_in = ngx_atoi(&value[i].data[8], value[i].len - 8); - } - + ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; u.default_port = 80; @@ -221,21 +218,19 @@ static char * ngx_http_upstream_dynamic_server_directive(ngx_conf_t *cf, ngx_com dynamic_server->host = u.host; dynamic_server->port = (in_port_t) (u.no_port ? u.default_port : u.port); - dynamic_server->refresh_in = refresh_in; - dynamic_server->debug_log = 0; + dynamic_server->refresh_in = 1000; } continue; } - if (ngx_strcmp(value[i].data, "debug_log") == 0) { - // enable debug log. this must be followed by resolve - if (dynamic_server) { - dynamic_server->debug_log = 1; - } + // add support for refresh_interval.this must be followed by resolve + if (dynamic_server && (ngx_strncmp(value[i].data, "refresh_interval=", 17) == 0)){ + dynamic_server->refresh_in = ngx_atoi(&value[i].data[17], value[i].len - 17); continue; } + // END CUSTOMIZATION goto invalid; @@ -314,7 +309,7 @@ static void *ngx_http_upstream_dynamic_server_main_conf(ngx_conf_t *cf) { } udsmcf->resolver_timeout = NGX_CONF_UNSET_MSEC; - + return udsmcf; } @@ -398,9 +393,8 @@ static void ngx_http_upstream_dynamic_server_resolve(ngx_event_t *ev) { ctx->data = dynamic_server; ctx->timeout = udsmcf->resolver_timeout; - if(dynamic_server && dynamic_server->debug_log) { - ngx_log_debug(NGX_LOG_DEBUG_CORE, ev->log, 0, "upstream-dynamic-servers: Resolving '%V'", &ctx->name); - } + ngx_log_debug(NGX_LOG_DEBUG_CORE, ev->log, 0, "upstream-dynamic-servers: Resolving '%V'", &ctx->name); + if (ngx_resolve_name(ctx) != NGX_OK) { ngx_log_error(NGX_LOG_ALERT, ev->log, 0, "upstream-dynamic-servers: ngx_resolve_name failed for '%V'", &ctx->name); ngx_add_timer(&dynamic_server->timer, 1000); @@ -414,13 +408,12 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t ngx_resolver_node_t *rn; ngx_pool_t *new_pool; ngx_addr_t *addrs; - ngx_uint_t refresh_in = 10000; + ngx_uint_t refresh_in = 1000; dynamic_server = ctx->data; - if(dynamic_server && dynamic_server->debug_log) { - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Finished resolving '%V'", &ctx->name); - } + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Finished resolving '%V'", &ctx->name); + if (ctx->state) { ngx_log_error(NGX_LOG_ERR, ctx->resolver->log, 0, "upstream-dynamic-servers: '%V' could not be resolved (%i: %s)", &ctx->name, ctx->state, ngx_resolver_strerror(ctx->state)); @@ -472,9 +465,8 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t } } - if(dynamic_server && dynamic_server->debug_log) { - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: No DNS changes for '%V' - keeping existing upstream configuration", &ctx->name); - } + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: No DNS changes for '%V' - keeping existing upstream configuration", &ctx->name); + goto end; reinit_upstream: @@ -485,9 +477,8 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t goto end; } - if(dynamic_server && dynamic_server->debug_log) { - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: DNS changes for '%V' detected - reinitializing upstream configuration", &ctx->name); - } + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: DNS changes for '%V' detected - reinitializing upstream configuration", &ctx->name); + ngx_memzero(&cf, sizeof(ngx_conf_t)); cf.name = "dynamic_server_init_upstream"; @@ -534,9 +525,8 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t len = ngx_sock_ntop(sockaddr, socklen, p, NGX_SOCKADDR_STRLEN, 1); addr->name.len = len; addr->name.data = p; - if(dynamic_server && dynamic_server->debug_log) { - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: '%V' was resolved to '%V'", &ctx->name, &addr->name); - } + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: '%V' was resolved to '%V'", &ctx->name, &addr->name); + } // If the domain failed to resolve, mark this server as down. @@ -573,9 +563,8 @@ static void ngx_http_upstream_dynamic_server_resolve_handler(ngx_resolver_ctx_t } } - if(dynamic_server && dynamic_server->debug_log) { - ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Refreshing DNS of '%V' in %ims", &ctx->name, refresh_in); - } + ngx_log_debug(NGX_LOG_DEBUG_CORE, ctx->resolver->log, 0, "upstream-dynamic-servers: Refreshing DNS of '%V' in %ims", &ctx->name, refresh_in); + } ngx_resolve_name_done(ctx); From d11999d32a89b10111b37cfdcfde84f34e8d9019 Mon Sep 17 00:00:00 2001 From: Rohit Joshi Date: Thu, 7 Jul 2016 15:46:22 -0400 Subject: [PATCH 6/6] Update README.md --- README.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6819c03..e446eec 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,8 @@ An nginx module to resolve domain names inside upstreams and keep them up to dat By default, servers defined in nginx upstreams are only resolved when nginx starts. This module provides an additional `resolve` parameter for `server` definitions that can be used to asynchronously resolve upstream domain names. This keeps the upstream definition up to date according to the DNS TTL of each domain names. This can be useful if you want to use upstreams for dynamic types of domain names that may frequently change IP addresses. +In addition to `resolve`, it allow optional `refresh_interval` to modify default value of 1000 (1s). + This module also allows nginx to start if an upstream contains a defunct domain name that no longer resolves. By default, nginx will fail to start if an upstream server contains an unresolvable domain name. With this module, nginx is still allowed to start with invalid domain names, but an error will be logged and the unresolvable domain names will be marked as down. ## Installation @@ -24,7 +26,7 @@ http { resolver 8.8.8.8; upstream example { - server example.com resolve; + server example.com resolve refresh_interval=1000; } } ``` @@ -49,6 +51,7 @@ The following parameters can be used (see nginx's [server documentation](http:// `backup` `down` `resolve` +`refresh_interval` # Compatibility