ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_rr_peer_data_t *rrp = data; time_t now; uintptr_t m; ngx_int_t rc; ngx_uint_t i, n; ngx_connection_t *c; ngx_http_upstream_rr_peer_t *peer; ngx_http_upstream_rr_peers_t *peers; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, try: %ui", pc->tries); now = ngx_time(); /* ngx_lock_mutex(rrp->peers->mutex); */ if (rrp->peers->last_cached) { /* cached connection */ c = rrp->peers->cached[rrp->peers->last_cached]; rrp->peers->last_cached--; /* ngx_unlock_mutex(ppr->peers->mutex); */ #if (NGX_THREADS) c->read->lock = c->read->own_lock; c->write->lock = c->write->own_lock; #endif pc->connection = c; pc->cached = 1; return NGX_OK; } pc->cached = 0; pc->connection = NULL; if (rrp->peers->single) { peer = &rrp->peers->peer[0]; } else { /* there are several peers */ if (pc->tries == rrp->peers->number) { /* it's a first try - get a current peer */ i = pc->tries; for ( ;; ) { rrp->current = ngx_http_upstream_get_peer(rrp->peers); ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, current: %ui %i", rrp->current, rrp->peers->peer[rrp->current].current_weight); n = rrp->current / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t)); if (!(rrp->tried[n] & m)) { peer = &rrp->peers->peer[rrp->current]; if (!peer->down) { if (peer->max_fails == 0 || peer->fails < peer->max_fails) { break; } if (now - peer->checked > peer->fail_timeout) { peer->checked = now; break; } peer->current_weight = 0; } else { rrp->tried[n] |= m; } pc->tries--; } if (pc->tries == 0) { goto failed; } if (--i == 0) { ngx_log_error(NGX_LOG_ALERT, pc->log, 0, "round robin upstream stuck on %ui tries", pc->tries); goto failed; } } peer->current_weight--; } else { i = pc->tries; for ( ;; ) { n = rrp->current / (8 * sizeof(uintptr_t)); m = (uintptr_t) 1 << rrp->current % (8 * sizeof(uintptr_t)); if (!(rrp->tried[n] & m)) { peer = &rrp->peers->peer[rrp->current]; if (!peer->down) { if (peer->max_fails == 0 || peer->fails < peer->max_fails) { break; } if (now - peer->checked > peer->fail_timeout) { peer->checked = now; break; } peer->current_weight = 0; } else { rrp->tried[n] |= m; } pc->tries--; } rrp->current++; if (rrp->current >= rrp->peers->number) { rrp->current = 0; } if (pc->tries == 0) { goto failed; } if (--i == 0) { ngx_log_error(NGX_LOG_ALERT, pc->log, 0, "round robin upstream stuck on %ui tries", pc->tries); goto failed; } } peer->current_weight--; } rrp->tried[n] |= m; } pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; /* ngx_unlock_mutex(rrp->peers->mutex); */ if (pc->tries == 1 && rrp->peers->next) { pc->tries += rrp->peers->next->number; n = rrp->peers->next->number / (8 * sizeof(uintptr_t)) + 1; for (i = 0; i < n; i++) { rrp->tried[i] = 0; } } return NGX_OK; failed: peers = rrp->peers; if (peers->next) { /* ngx_unlock_mutex(peers->mutex); */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers"); rrp->peers = peers->next; pc->tries = rrp->peers->number; n = rrp->peers->number / (8 * sizeof(uintptr_t)) + 1; for (i = 0; i < n; i++) { rrp->tried[i] = 0; } rc = ngx_http_upstream_get_round_robin_peer(pc, rrp); if (rc != NGX_BUSY) { return rc; } /* ngx_lock_mutex(peers->mutex); */ } /* all peers failed, mark them as live for quick recovery */ for (i = 0; i < peers->number; i++) { peers->peer[i].fails = 0; } /* ngx_unlock_mutex(peers->mutex); */ pc->name = peers->name; return NGX_BUSY; }
ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_rr_peer_data_t *rrp = data; ngx_int_t rc; ngx_uint_t i, n; ngx_http_upstream_rr_peer_t *peer; ngx_http_upstream_rr_peers_t *peers; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, try: %ui", pc->tries); pc->cached = 0; pc->connection = NULL; peers = rrp->peers; /* ngx_lock_mutex(peers->mutex); */ if (peers->single) { peer = &peers->peer[0]; if (peer->down) { goto failed; } } else { /* there are several peers */ peer = ngx_http_upstream_get_peer(rrp); if (peer == NULL) { goto failed; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, current: %ui %i", rrp->current, peer->current_weight); } pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; /* ngx_unlock_mutex(peers->mutex); */ return NGX_OK; failed: if (peers->next) { /* ngx_unlock_mutex(peers->mutex); */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers"); rrp->peers = peers->next; n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { rrp->tried[i] = 0; } rc = ngx_http_upstream_get_round_robin_peer(pc, rrp); if (rc != NGX_BUSY) { return rc; } /* ngx_lock_mutex(peers->mutex); */ } /* all peers failed, mark them as live for quick recovery */ for (i = 0; i < peers->number; i++) { peers->peer[i].fails = 0; } /* ngx_unlock_mutex(peers->mutex); */ pc->name = peers->name; return NGX_BUSY; }
ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_rr_peer_data_t *rrp = data; ngx_int_t rc; ngx_uint_t i, n; ngx_http_upstream_rr_peer_t *peer; ngx_http_upstream_rr_peers_t *peers; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, try: %ui", pc->tries); /* ngx_lock_mutex(rrp->peers->mutex); */ pc->cached = 0; pc->connection = NULL; if (rrp->peers->single) { peer = &rrp->peers->peer[0]; if (peer->down) { goto failed; } #if (NGX_HTTP_UPSTREAM_CHECK) if (ngx_http_upstream_check_peer_down(peer->check_index)) { goto failed; } #endif } else { /* there are several peers */ peer = ngx_http_upstream_get_peer(rrp); if (peer == NULL) { goto failed; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, current: %ui %i", rrp->current, peer->current_weight); } pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; pc->host = &peer->host; pc->dyn_resolve = peer->dyn_resolve; #if (NGX_DEBUG) struct sockaddr_in *in; in = (struct sockaddr_in *)peer->sockaddr; ngx_log_debug4(NGX_LOG_DEBUG_HTTP, pc->log, 0, "peer: %xd, %d, %V, %V", in->sin_addr.s_addr, peer->socklen, &peer->name, &peer->host); #endif /* ngx_unlock_mutex(rrp->peers->mutex); */ if (pc->tries == 1 && rrp->peers->next) { pc->tries += rrp->peers->next->number; } return NGX_OK; failed: peers = rrp->peers; if (peers->next) { /* ngx_unlock_mutex(peers->mutex); */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers"); rrp->peers = peers->next; pc->tries = rrp->peers->number; n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { rrp->tried[i] = 0; } rc = ngx_http_upstream_get_round_robin_peer(pc, rrp); if (rc != NGX_BUSY) { return rc; } /* ngx_lock_mutex(peers->mutex); */ } /* all peers failed, mark them as live for quick recovery */ for (i = 0; i < peers->number; i++) { peers->peer[i].fails = 0; } /* ngx_unlock_mutex(peers->mutex); */ pc->name = peers->name; return NGX_BUSY; }
ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_rr_peer_data_t *rrp = data; ngx_int_t rc; ngx_uint_t i, n; ngx_http_upstream_rr_peer_t *peer; ngx_http_upstream_rr_peers_t *peers; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, try: %ui", pc->tries); pc->cached = 0; pc->connection = NULL; peers = rrp->peers; ngx_http_upstream_rr_peers_wlock(peers); if (peers->single) { peer = peers->peer; if (peer->down) { goto failed; } if (peer->max_conns && peer->conns >= peer->max_conns) { goto failed; } rrp->current = peer; } else { /* there are several peers */ peer = ngx_http_upstream_get_peer(rrp); if (peer == NULL) { goto failed; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, current: %p %i", peer, peer->current_weight); } pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; peer->conns++; ngx_http_upstream_rr_peers_unlock(peers); return NGX_OK; failed: if (peers->next) { ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers"); rrp->peers = peers->next; n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { rrp->tried[i] = 0; } ngx_http_upstream_rr_peers_unlock(peers); rc = ngx_http_upstream_get_round_robin_peer(pc, rrp); if (rc != NGX_BUSY) { return rc; } ngx_http_upstream_rr_peers_wlock(peers); } ngx_http_upstream_rr_peers_unlock(peers); pc->name = peers->name; return NGX_BUSY; }
ngx_int_t ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) { ngx_http_upstream_rr_peer_data_t *rrp = data; ngx_int_t rc; ngx_uint_t i, n; ngx_connection_t *c; ngx_http_upstream_rr_peer_t *peer; ngx_http_upstream_rr_peers_t *peers; ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, try: %ui", pc->tries); /* ngx_lock_mutex(rrp->peers->mutex); */ if (rrp->peers->last_cached) { /* cached connection */ c = rrp->peers->cached[rrp->peers->last_cached]; rrp->peers->last_cached--; /* ngx_unlock_mutex(ppr->peers->mutex); */ #if (NGX_THREADS) c->read->lock = c->read->own_lock; c->write->lock = c->write->own_lock; #endif pc->connection = c; pc->cached = 1; return NGX_OK; } pc->cached = 0; pc->connection = NULL; if (rrp->peers->single) { peer = &rrp->peers->peer[0]; if (peer->down) { goto failed; } #if (NGX_HTTP_UPSTREAM_CHECK) if (ngx_http_upstream_check_peer_down(peer->check_index)) { goto failed; } #endif } else { /* there are several peers */ peer = ngx_http_upstream_get_peer(rrp); if (peer == NULL) { goto failed; } ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get rr peer, current: %ui %i", rrp->current, peer->current_weight); } pc->sockaddr = peer->sockaddr; pc->socklen = peer->socklen; pc->name = &peer->name; /* ngx_unlock_mutex(rrp->peers->mutex); */ if (pc->tries == 1 && rrp->peers->next) { pc->tries += rrp->peers->next->number; } return NGX_OK; failed: peers = rrp->peers; if (peers->next) { /* ngx_unlock_mutex(peers->mutex); */ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "backup servers"); rrp->peers = peers->next; pc->tries = rrp->peers->number; n = (rrp->peers->number + (8 * sizeof(uintptr_t) - 1)) / (8 * sizeof(uintptr_t)); for (i = 0; i < n; i++) { rrp->tried[i] = 0; } rc = ngx_http_upstream_get_round_robin_peer(pc, rrp); if (rc != NGX_BUSY) { return rc; } /* ngx_lock_mutex(peers->mutex); */ } /* all peers failed, mark them as live for quick recovery */ for (i = 0; i < peers->number; i++) { peers->peer[i].fails = 0; } /* ngx_unlock_mutex(peers->mutex); */ pc->name = peers->name; return NGX_BUSY; }