aboutsummaryrefslogtreecommitdiff
path: root/src/stream/ngx_stream_upstream_round_robin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/stream/ngx_stream_upstream_round_robin.c')
-rw-r--r--src/stream/ngx_stream_upstream_round_robin.c204
1 files changed, 194 insertions, 10 deletions
diff --git a/src/stream/ngx_stream_upstream_round_robin.c b/src/stream/ngx_stream_upstream_round_robin.c
index ae3bf37a6..a18171a39 100644
--- a/src/stream/ngx_stream_upstream_round_robin.c
+++ b/src/stream/ngx_stream_upstream_round_robin.c
@@ -38,10 +38,15 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
ngx_stream_upstream_srv_conf_t *us)
{
ngx_url_t u;
- ngx_uint_t i, j, n, w, t;
+ ngx_uint_t i, j, n, r, w, t;
ngx_stream_upstream_server_t *server;
ngx_stream_upstream_rr_peer_t *peer, **peerp;
ngx_stream_upstream_rr_peers_t *peers, *backup;
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ ngx_uint_t resolve;
+ ngx_stream_core_srv_conf_t *cscf;
+ ngx_stream_upstream_rr_peer_t **rpeerp;
+#endif
us->peer.init = ngx_stream_upstream_init_round_robin_peer;
@@ -49,14 +54,33 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
server = us->servers->elts;
n = 0;
+ r = 0;
w = 0;
t = 0;
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ resolve = 0;
+#endif
+
for (i = 0; i < us->servers->nelts; i++) {
+
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ if (server[i].host.len) {
+ resolve = 1;
+ }
+#endif
+
if (server[i].backup) {
continue;
}
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ if (server[i].host.len) {
+ r++;
+ continue;
+ }
+#endif
+
n += server[i].naddrs;
w += server[i].naddrs * server[i].weight;
@@ -65,7 +89,54 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
}
}
- if (n == 0) {
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ if (us->shm_zone) {
+
+ if (resolve && !(us->flags & NGX_STREAM_UPSTREAM_MODIFY)) {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "load balancing method does not support"
+ " resolving names at run time in"
+ " upstream \"%V\" in %s:%ui",
+ &us->host, us->file_name, us->line);
+ return NGX_ERROR;
+ }
+
+ cscf = ngx_stream_conf_get_module_srv_conf(cf,
+ ngx_stream_core_module);
+
+ us->resolver = cscf->resolver;
+ us->resolver_timeout = cscf->resolver_timeout;
+
+ /*
+ * Without "resolver_timeout" in stream{}, the value is unset.
+ * Even if we set it in ngx_stream_core_merge_srv_conf(), it's
+ * still dependent on the module order and unreliable.
+ */
+ ngx_conf_init_msec_value(us->resolver_timeout, 30000);
+
+ if (resolve
+ && (us->resolver == NULL
+ || us->resolver->connections.nelts == 0))
+ {
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "no resolver defined to resolve names"
+ " at run time in upstream \"%V\" in %s:%ui",
+ &us->host, us->file_name, us->line);
+ return NGX_ERROR;
+ }
+
+ } else if (resolve) {
+
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
+ "resolving names at run time requires"
+ " upstream \"%V\" in %s:%ui"
+ " to be in shared memory",
+ &us->host, us->file_name, us->line);
+ return NGX_ERROR;
+ }
+#endif
+
+ if (n + r == 0) {
ngx_log_error(NGX_LOG_EMERG, cf->log, 0,
"no servers in upstream \"%V\" in %s:%ui",
&us->host, us->file_name, us->line);
@@ -77,7 +148,8 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
return NGX_ERROR;
}
- peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n);
+ peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t)
+ * (n + r));
if (peer == NULL) {
return NGX_ERROR;
}
@@ -92,11 +164,45 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
n = 0;
peerp = &peers->peer;
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ rpeerp = &peers->resolve;
+#endif
+
for (i = 0; i < us->servers->nelts; i++) {
if (server[i].backup) {
continue;
}
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ if (server[i].host.len) {
+
+ peer[n].host = ngx_pcalloc(cf->pool,
+ sizeof(ngx_stream_upstream_host_t));
+ if (peer[n].host == NULL) {
+ return NGX_ERROR;
+ }
+
+ peer[n].host->name = server[i].host;
+
+ peer[n].sockaddr = server[i].addrs[0].sockaddr;
+ peer[n].socklen = server[i].addrs[0].socklen;
+ peer[n].name = server[i].addrs[0].name;
+ peer[n].weight = server[i].weight;
+ peer[n].effective_weight = server[i].weight;
+ peer[n].current_weight = 0;
+ peer[n].max_conns = server[i].max_conns;
+ peer[n].max_fails = server[i].max_fails;
+ peer[n].fail_timeout = server[i].fail_timeout;
+ peer[n].down = server[i].down;
+ peer[n].server = server[i].name;
+ *rpeerp = &peer[n];
+ rpeerp = &peer[n].next;
+ n++;
+
+ continue;
+ }
+#endif
+
for (j = 0; j < server[i].naddrs; j++) {
peer[n].sockaddr = server[i].addrs[j].sockaddr;
peer[n].socklen = server[i].addrs[j].socklen;
@@ -121,6 +227,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
/* backup servers */
n = 0;
+ r = 0;
w = 0;
t = 0;
@@ -129,6 +236,13 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
continue;
}
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ if (server[i].host.len) {
+ r++;
+ continue;
+ }
+#endif
+
n += server[i].naddrs;
w += server[i].naddrs * server[i].weight;
@@ -137,7 +251,7 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
}
}
- if (n == 0) {
+ if (n + r == 0) {
return NGX_OK;
}
@@ -146,12 +260,16 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
return NGX_ERROR;
}
- peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t) * n);
+ peer = ngx_pcalloc(cf->pool, sizeof(ngx_stream_upstream_rr_peer_t)
+ * (n + r));
if (peer == NULL) {
return NGX_ERROR;
}
- peers->single = 0;
+ if (n > 0) {
+ peers->single = 0;
+ }
+
backup->single = 0;
backup->number = n;
backup->weighted = (w != n);
@@ -162,11 +280,45 @@ ngx_stream_upstream_init_round_robin(ngx_conf_t *cf,
n = 0;
peerp = &backup->peer;
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ rpeerp = &backup->resolve;
+#endif
+
for (i = 0; i < us->servers->nelts; i++) {
if (!server[i].backup) {
continue;
}
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ if (server[i].host.len) {
+
+ peer[n].host = ngx_pcalloc(cf->pool,
+ sizeof(ngx_stream_upstream_host_t));
+ if (peer[n].host == NULL) {
+ return NGX_ERROR;
+ }
+
+ peer[n].host->name = server[i].host;
+
+ peer[n].sockaddr = server[i].addrs[0].sockaddr;
+ peer[n].socklen = server[i].addrs[0].socklen;
+ peer[n].name = server[i].addrs[0].name;
+ peer[n].weight = server[i].weight;
+ peer[n].effective_weight = server[i].weight;
+ peer[n].current_weight = 0;
+ peer[n].max_conns = server[i].max_conns;
+ peer[n].max_fails = server[i].max_fails;
+ peer[n].fail_timeout = server[i].fail_timeout;
+ peer[n].down = server[i].down;
+ peer[n].server = server[i].name;
+ *rpeerp = &peer[n];
+ rpeerp = &peer[n].next;
+ n++;
+
+ continue;
+ }
+#endif
+
for (j = 0; j < server[i].naddrs; j++) {
peer[n].sockaddr = server[i].addrs[j].sockaddr;
peer[n].socklen = server[i].addrs[j].socklen;
@@ -280,7 +432,12 @@ ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s,
rrp->peers = us->peer.data;
rrp->current = NULL;
- rrp->config = 0;
+
+ ngx_stream_upstream_rr_peers_rlock(rrp->peers);
+
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ rrp->config = rrp->peers->config ? *rrp->peers->config : 0;
+#endif
n = rrp->peers->number;
@@ -288,6 +445,10 @@ ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s,
n = rrp->peers->next->number;
}
+ s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers);
+
+ ngx_stream_upstream_rr_peers_unlock(rrp->peers);
+
if (n <= 8 * sizeof(uintptr_t)) {
rrp->tried = &rrp->data;
rrp->data = 0;
@@ -304,7 +465,7 @@ ngx_stream_upstream_init_round_robin_peer(ngx_stream_session_t *s,
s->upstream->peer.get = ngx_stream_upstream_get_round_robin_peer;
s->upstream->peer.free = ngx_stream_upstream_free_round_robin_peer;
s->upstream->peer.notify = ngx_stream_upstream_notify_round_robin_peer;
- s->upstream->peer.tries = ngx_stream_upstream_tries(rrp->peers);
+
#if (NGX_STREAM_SSL)
s->upstream->peer.set_session =
ngx_stream_upstream_set_round_robin_peer_session;
@@ -455,6 +616,12 @@ ngx_stream_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
peers = rrp->peers;
ngx_stream_upstream_rr_peers_wlock(peers);
+#if (NGX_STREAM_UPSTREAM_ZONE)
+ if (peers->config && rrp->config != *peers->config) {
+ goto busy;
+ }
+#endif
+
if (peers->single) {
peer = peers->peer;
@@ -467,6 +634,7 @@ ngx_stream_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
}
rrp->current = peer;
+ ngx_stream_upstream_rr_peer_ref(peers, peer);
} else {
@@ -519,6 +687,10 @@ failed:
ngx_stream_upstream_rr_peers_wlock(peers);
}
+#if (NGX_STREAM_UPSTREAM_ZONE)
+busy:
+#endif
+
ngx_stream_upstream_rr_peers_unlock(peers);
pc->name = peers->name;
@@ -589,6 +761,7 @@ ngx_stream_upstream_get_peer(ngx_stream_upstream_rr_peer_data_t *rrp)
}
rrp->current = best;
+ ngx_stream_upstream_rr_peer_ref(rrp->peers, best);
n = p / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
@@ -623,9 +796,17 @@ ngx_stream_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
ngx_stream_upstream_rr_peer_lock(rrp->peers, peer);
if (rrp->peers->single) {
+
+ if (peer->fails) {
+ peer->fails = 0;
+ }
+
peer->conns--;
- ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer);
+ if (ngx_stream_upstream_rr_peer_unref(rrp->peers, peer) == NGX_OK) {
+ ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer);
+ }
+
ngx_stream_upstream_rr_peers_unlock(rrp->peers);
pc->tries = 0;
@@ -667,7 +848,10 @@ ngx_stream_upstream_free_round_robin_peer(ngx_peer_connection_t *pc, void *data,
peer->conns--;
- ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer);
+ if (ngx_stream_upstream_rr_peer_unref(rrp->peers, peer) == NGX_OK) {
+ ngx_stream_upstream_rr_peer_unlock(rrp->peers, peer);
+ }
+
ngx_stream_upstream_rr_peers_unlock(rrp->peers);
if (pc->tries) {