]> git.kaiwu.me - nginx.git/commitdiff
Resolver: per-request DNS server balancer.
authorRoman Arutyunyan <arut@nginx.com>
Thu, 28 Jan 2016 12:28:20 +0000 (15:28 +0300)
committerRoman Arutyunyan <arut@nginx.com>
Thu, 28 Jan 2016 12:28:20 +0000 (15:28 +0300)
Previously, a global server balancer was used to assign the next DNS server to
send a query to.  That could lead to a non-uniform distribution of servers per
request.  A request could be assigned to the same dead server several times in a
row and wait longer for a valid server or even time out without being processed.

Now each query is sent to all servers sequentially in a circle until a
response is received or timeout expires.  Initial server for each request is
still globally balanced.

src/core/ngx_resolver.c
src/core/ngx_resolver.h

index a9185529e1f6e44767ca45114e79807664659fcf..ac0d54dcd7915f7552f2c4482576a9e1f761ec89 100644 (file)
@@ -685,6 +685,11 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx,
         return NGX_OK;
     }
 
+    rn->last_connection = r->last_connection++;
+    if (r->last_connection == r->connections.nelts) {
+        r->last_connection = 0;
+    }
+
     rn->naddrs = (u_short) -1;
 #if (NGX_HAVE_INET6)
     rn->naddrs6 = r->ipv6 ? (u_short) -1 : 0;
@@ -897,6 +902,11 @@ ngx_resolve_addr(ngx_resolver_ctx_t *ctx)
         goto failed;
     }
 
+    rn->last_connection = r->last_connection++;
+    if (r->last_connection == r->connections.nelts) {
+        r->last_connection = 0;
+    }
+
     rn->naddrs = (u_short) -1;
 #if (NGX_HAVE_INET6)
     rn->naddrs6 = (u_short) -1;
@@ -1098,11 +1108,7 @@ ngx_resolver_send_query(ngx_resolver_t *r, ngx_resolver_node_t *rn)
     ngx_resolver_connection_t  *rec;
 
     rec = r->connections.elts;
-
-    rec = &rec[r->last_connection++];
-    if (r->last_connection == r->connections.nelts) {
-        r->last_connection = 0;
-    }
+    rec = &rec[rn->last_connection];
 
     if (rec->udp == NULL) {
 
@@ -1244,6 +1250,10 @@ ngx_resolver_resend(ngx_resolver_t *r, ngx_rbtree_t *tree, ngx_queue_t *queue)
 
         if (rn->waiting) {
 
+            if (++rn->last_connection == r->connections.nelts) {
+                rn->last_connection = 0;
+            }
+
             (void) ngx_resolver_send_query(r, rn);
 
             rn->expire = now + r->resend_timeout;
index 5aedabfaa2804fced0032a8de482c7c4aa3d569e..ab4ae74eec933b284842cdaf3306092e9fa2fe9d 100644 (file)
@@ -93,6 +93,8 @@ typedef struct {
     time_t                    valid;
     uint32_t                  ttl;
 
+    ngx_uint_t                last_connection;
+
     ngx_resolver_ctx_t       *waiting;
 } ngx_resolver_node_t;