]> git.kaiwu.me - nginx.git/commitdiff
Resolver: cached addresses are returned with random rotation now.
authorMaxim Dounin <mdounin@mdounin.ru>
Fri, 28 Sep 2012 18:28:38 +0000 (18:28 +0000)
committerMaxim Dounin <mdounin@mdounin.ru>
Fri, 28 Sep 2012 18:28:38 +0000 (18:28 +0000)
This ensures balancing when working with dynamically resolved upstream
servers with multiple addresses.

Based on patch by Anton Jouline.

src/core/ngx_resolver.c

index 178e0831d56177c6cf073f849c992a1a3371bcbb..dcdbe0cc8faa18eb2d2e91ccf3749d595e7ad323 100644 (file)
@@ -88,6 +88,8 @@ static void *ngx_resolver_calloc(ngx_resolver_t *r, size_t size);
 static void ngx_resolver_free(ngx_resolver_t *r, void *p);
 static void ngx_resolver_free_locked(ngx_resolver_t *r, void *p);
 static void *ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size);
+static in_addr_t *ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src,
+    ngx_uint_t n);
 static u_char *ngx_resolver_log_error(ngx_log_t *log, u_char *buf, size_t len);
 
 
@@ -445,8 +447,7 @@ ngx_resolve_name_locked(ngx_resolver_t *r, ngx_resolver_ctx_t *ctx)
 
                 if (naddrs != 1) {
                     addr = 0;
-                    addrs = ngx_resolver_dup(r, rn->u.addrs,
-                                             naddrs * sizeof(in_addr_t));
+                    addrs = ngx_resolver_rotate(r, rn->u.addrs, naddrs);
                     if (addrs == NULL) {
                         return NGX_ERROR;
                     }
@@ -2135,6 +2136,28 @@ ngx_resolver_dup(ngx_resolver_t *r, void *src, size_t size)
 }
 
 
+static in_addr_t *
+ngx_resolver_rotate(ngx_resolver_t *r, in_addr_t *src, ngx_uint_t n)
+{
+    void        *dst, *p;
+    ngx_uint_t   j;
+
+    dst = ngx_resolver_alloc(r, n * sizeof(in_addr_t));
+
+    j = ngx_random() % n;
+
+    if (j == 0) {
+        ngx_memcpy(dst, src, n * sizeof(in_addr_t));
+        return dst;
+    }
+
+    p = ngx_cpymem(dst, &src[j], (n - j) * sizeof(in_addr_t));
+    ngx_memcpy(p, src, j * sizeof(in_addr_t));
+
+    return dst;
+}
+
+
 char *
 ngx_resolver_strerror(ngx_int_t err)
 {