diff options
| author | Maxim Dounin <mdounin@mdounin.ru> | 2012-09-28 18:28:38 +0000 |
|---|---|---|
| committer | Maxim Dounin <mdounin@mdounin.ru> | 2012-09-28 18:28:38 +0000 |
| commit | 6a0f47e0797c8b797c806fab16ffc5bab40c0577 (patch) | |
| tree | 140ef99d3521f30e2316ab22242eae74724af3b2 | |
| parent | 8be233c8f2a3544195be4a6e97243437cd78df60 (diff) | |
| download | nginx-6a0f47e0797c8b797c806fab16ffc5bab40c0577.tar.gz nginx-6a0f47e0797c8b797c806fab16ffc5bab40c0577.tar.bz2 | |
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 | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/src/core/ngx_resolver.c b/src/core/ngx_resolver.c index 178e0831d..dcdbe0cc8 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,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) { |
