diff options
| author | Maxim Dounin <mdounin@mdounin.ru> | 2012-11-12 18:47:07 +0000 |
|---|---|---|
| committer | Maxim Dounin <mdounin@mdounin.ru> | 2012-11-12 18:47:07 +0000 |
| commit | 0e6c7b0614eafd628c2abe93e5418599a025b552 (patch) | |
| tree | 8a11874937ca0620b9e2e9ec037e5c9cc2f41357 | |
| parent | 033598bc073da23dcec5e4ea80b85cccecd8958a (diff) | |
| download | nginx-0e6c7b0614eafd628c2abe93e5418599a025b552.tar.gz nginx-0e6c7b0614eafd628c2abe93e5418599a025b552.tar.bz2 | |
Merge of r4872, r4893: resolver cached addresses random rotation.
Resolver: cached addresses are returned with random rotation now.
This ensures balancing when working with dynamically resolved upstream
servers with multiple addresses.
Based on patch by Anton Jouline.
| -rw-r--r-- | src/core/ngx_resolver.c | 31 |
1 files changed, 29 insertions, 2 deletions
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 178e0831d..d59d0c471 100644 --- a/src/core/ngx_resolver.c +++ b/src/core/ngx_resolver.c @@ -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,32 @@ 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)); + + if (dst == NULL) { + return dst; + } + + 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) { |
