]> git.feebdaed.xyz Git - 0xmirror/nginx.git/commitdiff
Upstream: copy upstream zone DNS valid time during config reload.
authorMini Hawthorne <mini@f5.com>
Wed, 12 Jul 2023 19:20:45 +0000 (12:20 -0700)
committerAleksei Bavshin <a.bavshin@f5.com>
Thu, 7 Nov 2024 15:57:42 +0000 (07:57 -0800)
Previously, all upstream DNS entries would be immediately re-resolved
on config reload.  With a large number of upstreams, this creates
a spike of DNS resolution requests.  These spikes can overwhelm the
DNS server or cause drops on the network.

This patch retains the TTL of previous resolutions across reloads
by copying each upstream's name's expiry time across configuration
cycles.  As a result, no additional resolutions are needed.

src/http/modules/ngx_http_upstream_zone_module.c
src/http/ngx_http_upstream_round_robin.h
src/stream/ngx_stream_upstream_round_robin.h
src/stream/ngx_stream_upstream_zone_module.c

index c1931a8bb7e554aaa1bc54ea2531bca1be83530b..2ce8a7b5b55273d05c3fb3e164f1954587a6e8b2 100644 (file)
@@ -545,6 +545,8 @@ ngx_http_upstream_zone_preresolve(ngx_http_upstream_rr_peer_t *resolve,
 
                 peer->host = template->host;
 
+                template->host->valid = host->valid;
+
                 server = template->host->service.len ? &opeer->server
                                                      : &template->server;
 
@@ -626,6 +628,8 @@ ngx_http_upstream_zone_remove_peer_locked(ngx_http_upstream_rr_peers_t *peers,
 static ngx_int_t
 ngx_http_upstream_zone_init_worker(ngx_cycle_t *cycle)
 {
+    time_t                          now;
+    ngx_msec_t                      timer;
     ngx_uint_t                      i;
     ngx_event_t                    *event;
     ngx_http_upstream_rr_peer_t    *peer;
@@ -639,6 +643,7 @@ ngx_http_upstream_zone_init_worker(ngx_cycle_t *cycle)
         return NGX_OK;
     }
 
+    now = ngx_time();
     umcf = ngx_http_cycle_get_module_main_conf(cycle, ngx_http_upstream_module);
 
     if (umcf == NULL) {
@@ -674,7 +679,10 @@ ngx_http_upstream_zone_init_worker(ngx_cycle_t *cycle)
                 event->log = cycle->log;
                 event->cancelable = 1;
 
-                ngx_add_timer(event, 1);
+                timer = (peer->host->valid > now)
+                        ? (ngx_msec_t) 1000 * (peer->host->valid - now) : 1;
+
+                ngx_add_timer(event, timer);
             }
 
             ngx_http_upstream_rr_peers_unlock(peers);
@@ -983,6 +991,8 @@ again:
 
 done:
 
+    host->valid = ctx->valid;
+
     ngx_http_upstream_rr_peers_unlock(peers);
 
     while (++i < ctx->naddrs) {
index 084b0b8869c1f025497f57aa14dc3259d35e7f96..2f0a51cdf2a6291ea4fef2030c1bf336f14e159d 100644 (file)
@@ -25,6 +25,7 @@ typedef struct {
     ngx_uint_t                      worker;
     ngx_str_t                       name;
     ngx_str_t                       service;
+    time_t                          valid;
     ngx_http_upstream_rr_peers_t   *peers;
     ngx_http_upstream_rr_peer_t    *peer;
 } ngx_http_upstream_host_t;
index 707a9889dbfdd8d072ffb7c09ad315d0d345b15a..c168bfe80146fcc01b8a72752598be1481afc182 100644 (file)
@@ -25,6 +25,7 @@ typedef struct {
     ngx_uint_t                       worker;
     ngx_str_t                        name;
     ngx_str_t                        service;
+    time_t                           valid;
     ngx_stream_upstream_rr_peers_t  *peers;
     ngx_stream_upstream_rr_peer_t   *peer;
 } ngx_stream_upstream_host_t;
index d92609febc69b7d6c8f4f317200add178355ae99..a6874dc33d549cd32a080fd6e280c6351dac97ec 100644 (file)
@@ -542,6 +542,8 @@ ngx_stream_upstream_zone_preresolve(ngx_stream_upstream_rr_peer_t *resolve,
 
                 peer->host = template->host;
 
+                template->host->valid = host->valid;
+
                 server = template->host->service.len ? &opeer->server
                                                      : &template->server;
 
@@ -623,6 +625,8 @@ ngx_stream_upstream_zone_remove_peer_locked(
 static ngx_int_t
 ngx_stream_upstream_zone_init_worker(ngx_cycle_t *cycle)
 {
+    time_t                            now;
+    ngx_msec_t                        timer;
     ngx_uint_t                        i;
     ngx_event_t                      *event;
     ngx_stream_upstream_rr_peer_t    *peer;
@@ -636,6 +640,7 @@ ngx_stream_upstream_zone_init_worker(ngx_cycle_t *cycle)
         return NGX_OK;
     }
 
+    now = ngx_time();
     umcf = ngx_stream_cycle_get_module_main_conf(cycle,
                                                  ngx_stream_upstream_module);
 
@@ -672,7 +677,10 @@ ngx_stream_upstream_zone_init_worker(ngx_cycle_t *cycle)
                 event->log = cycle->log;
                 event->cancelable = 1;
 
-                ngx_add_timer(event, 1);
+                timer = (peer->host->valid > now)
+                        ? (ngx_msec_t) 1000 * (peer->host->valid - now) : 1;
+
+                ngx_add_timer(event, timer);
             }
 
             ngx_stream_upstream_rr_peers_unlock(peers);
@@ -981,6 +989,8 @@ again:
 
 done:
 
+    host->valid = ctx->valid;
+
     ngx_stream_upstream_rr_peers_unlock(peers);
 
     while (++i < ctx->naddrs) {