static ngx_int_t
ngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data)
{
    ngx_http_upstream_random_peer_data_t  *rp = data;
    time_t                             now;
    uintptr_t                          m;
    ngx_uint_t                         i, n;
    ngx_http_upstream_rr_peer_t       *peer;
    ngx_http_upstream_rr_peers_t      *peers;
    ngx_http_upstream_rr_peer_data_t  *rrp;
    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,
                   "get random peer, try: %ui", pc->tries);
    rrp = &rp->rrp;
    peers = rrp->peers;
    ngx_http_upstream_rr_peers_rlock(peers);
    if (rp->tries > 20 || peers->single) {
        ngx_http_upstream_rr_peers_unlock(peers);
        return ngx_http_upstream_get_round_robin_peer(pc, rrp);
    }
    pc->cached = 0;
    pc->connection = NULL;
    now = ngx_time();
    for ( ;; ) {
        i = ngx_http_upstream_peek_random_peer(peers, rp);
        peer = rp->conf->ranges[i].peer;
        n = i / (8 * sizeof(uintptr_t));
        m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));
        if (rrp->tried[n] & m) {
            goto next;
        }
        ngx_http_upstream_rr_peer_lock(peers, peer);
        if (peer->down) {
            ngx_http_upstream_rr_peer_unlock(peers, peer);
            goto next;
        }
        if (peer->max_fails
            && peer->fails >= peer->max_fails
            && now - peer->checked <= peer->fail_timeout)
        {
            ngx_http_upstream_rr_peer_unlock(peers, peer);
            goto next;
        }
        if (peer->max_conns && peer->conns >= peer->max_conns) {
            ngx_http_upstream_rr_peer_unlock(peers, peer);
            goto next;
        }
        break;
    next:
        if (++rp->tries > 20) {
            ngx_http_upstream_rr_peers_unlock(peers);
            return ngx_http_upstream_get_round_robin_peer(pc, rrp);
        }
    }
    rrp->current = peer;
    if (now - peer->checked > peer->fail_timeout) {
        peer->checked = now;
    }
    pc->sockaddr = peer->sockaddr;
    pc->socklen = peer->socklen;
    pc->name = &peer->name;
    peer->conns++;
    ngx_http_upstream_rr_peer_unlock(peers, peer);
    ngx_http_upstream_rr_peers_unlock(peers);
    rrp->tried[n] |= m;
    return NGX_OK;
}
['static ngx_int_t\nngx_http_upstream_get_random_peer(ngx_peer_connection_t *pc, void *data)\n{\n    ngx_http_upstream_random_peer_data_t  *rp = data;\n    time_t                             now;\n    uintptr_t                          m;\n    ngx_uint_t                         i, n;\n    ngx_http_upstream_rr_peer_t       *peer;\n    ngx_http_upstream_rr_peers_t      *peers;\n    ngx_http_upstream_rr_peer_data_t  *rrp;\n    ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0,\n                   "get random peer, try: %ui", pc->tries);\n    rrp = &rp->rrp;\n    peers = rrp->peers;\n    ngx_http_upstream_rr_peers_rlock(peers);\n    if (rp->tries > 20 || peers->single) {\n        ngx_http_upstream_rr_peers_unlock(peers);\n        return ngx_http_upstream_get_round_robin_peer(pc, rrp);\n    }\n    pc->cached = 0;\n    pc->connection = NULL;\n    now = ngx_time();\n    for ( ;; ) {\n        i = ngx_http_upstream_peek_random_peer(peers, rp);\n        peer = rp->conf->ranges[i].peer;\n        n = i / (8 * sizeof(uintptr_t));\n        m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t));\n        if (rrp->tried[n] & m) {\n            goto next;\n        }\n        ngx_http_upstream_rr_peer_lock(peers, peer);\n        if (peer->down) {\n            ngx_http_upstream_rr_peer_unlock(peers, peer);\n            goto next;\n        }\n        if (peer->max_fails\n            && peer->fails >= peer->max_fails\n            && now - peer->checked <= peer->fail_timeout)\n        {\n            ngx_http_upstream_rr_peer_unlock(peers, peer);\n            goto next;\n        }\n        if (peer->max_conns && peer->conns >= peer->max_conns) {\n            ngx_http_upstream_rr_peer_unlock(peers, peer);\n            goto next;\n        }\n        break;\n    next:\n        if (++rp->tries > 20) {\n            ngx_http_upstream_rr_peers_unlock(peers);\n            return ngx_http_upstream_get_round_robin_peer(pc, rrp);\n        }\n    }\n    rrp->current = peer;\n    if (now - peer->checked > peer->fail_timeout) {\n        peer->checked = now;\n    }\n    pc->sockaddr = peer->sockaddr;\n    pc->socklen = peer->socklen;\n    pc->name = &peer->name;\n    peer->conns++;\n    ngx_http_upstream_rr_peer_unlock(peers, peer);\n    ngx_http_upstream_rr_peers_unlock(peers);\n    rrp->tried[n] |= m;\n    return NGX_OK;\n}']