Resolver: per-request DNS server balancer.

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.
This commit is contained in:
Roman Arutyunyan 2016-01-28 15:28:20 +03:00
parent f76fcebd3c
commit 1e17ee9366
2 changed files with 17 additions and 5 deletions

View 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;

View 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;