This commit is contained in:
Roman Arutyunyan 2026-07-09 16:39:09 +01:00 committed by GitHub
commit 97b0cca7de
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 98 additions and 10 deletions

View file

@ -69,6 +69,7 @@ struct ngx_peer_connection_s {
unsigned transparent:1;
unsigned so_keepalive:1;
unsigned down:1;
unsigned unique:1;
/* ngx_connection_log_error_e */
unsigned log_error:2;

View file

@ -575,6 +575,20 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_timeout),
NULL },
{ ngx_string("proxy_next_upstream_delay"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_msec_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_delay),
NULL },
{ ngx_string("proxy_next_upstream_unique"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot,
NGX_HTTP_LOC_CONF_OFFSET,
offsetof(ngx_http_proxy_loc_conf_t, upstream.next_upstream_unique),
NULL },
{ ngx_string("proxy_pass_header"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
ngx_conf_set_str_array_slot,
@ -3524,6 +3538,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.request_buffering = NGX_CONF_UNSET;
conf->upstream.ignore_client_abort = NGX_CONF_UNSET;
conf->upstream.force_ranges = NGX_CONF_UNSET;
conf->upstream.next_upstream_unique = NGX_CONF_UNSET;
conf->upstream.local = NGX_CONF_UNSET_PTR;
conf->upstream.socket_keepalive = NGX_CONF_UNSET;
@ -3532,6 +3547,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.send_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.read_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.next_upstream_timeout = NGX_CONF_UNSET_MSEC;
conf->upstream.next_upstream_delay = NGX_CONF_UNSET_MSEC;
conf->upstream.send_lowat = NGX_CONF_UNSET_SIZE;
conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE;
@ -3656,6 +3672,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_value(conf->upstream.force_ranges,
prev->upstream.force_ranges, 0);
ngx_conf_merge_value(conf->upstream.next_upstream_unique,
prev->upstream.next_upstream_unique, 1);
ngx_conf_merge_ptr_value(conf->upstream.local,
prev->upstream.local, NULL);
@ -3674,6 +3693,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.next_upstream_timeout,
prev->upstream.next_upstream_timeout, 0);
ngx_conf_merge_msec_value(conf->upstream.next_upstream_delay,
prev->upstream.next_upstream_delay, 0);
ngx_conf_merge_size_value(conf->upstream.send_lowat,
prev->upstream.send_lowat, 0);

View file

@ -308,7 +308,9 @@ found:
ngx_http_upstream_rr_peer_unlock(hp->rrp.peers, peer);
ngx_http_upstream_rr_peers_unlock(hp->rrp.peers);
hp->rrp.tried[n] |= m;
if (pc->unique) {
hp->rrp.tried[n] |= m;
}
return NGX_OK;
}
@ -713,7 +715,9 @@ found:
n = best_i / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << best_i % (8 * sizeof(uintptr_t));
hp->rrp.tried[n] |= m;
if (pc->unique) {
hp->rrp.tried[n] |= m;
}
return NGX_OK;
}

View file

@ -271,7 +271,9 @@ best_chosen:
n = p / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
rrp->tried[n] |= m;
if (pc->unique) {
rrp->tried[n] |= m;
}
ngx_http_upstream_rr_peers_unlock(peers);

View file

@ -327,7 +327,9 @@ found:
ngx_http_upstream_rr_peer_unlock(peers, peer);
ngx_http_upstream_rr_peers_unlock(peers);
rrp->tried[n] |= m;
if (pc->unique) {
rrp->tried[n] |= m;
}
return NGX_OK;
}
@ -463,7 +465,9 @@ found:
ngx_http_upstream_rr_peers_unlock(peers);
rrp->tried[n] |= m;
if (pc->unique) {
rrp->tried[n] |= m;
}
return NGX_OK;
}

View file

@ -99,6 +99,7 @@ static void ngx_http_upstream_dummy_handler(ngx_http_request_t *r,
static void ngx_http_upstream_next(ngx_http_request_t *r,
ngx_http_upstream_t *u, ngx_uint_t ft_type);
static void ngx_http_upstream_cleanup(void *data);
static void ngx_http_upstream_connect_handler(ngx_event_t *ev);
static void ngx_http_upstream_finalize_request(ngx_http_request_t *r,
ngx_http_upstream_t *u, ngx_int_t rc);
@ -844,9 +845,10 @@ found:
}
u->peer.start_time = ngx_current_msec;
u->peer.unique = u->conf->next_upstream_unique;
if (u->conf->next_upstream_tries
&& u->peer.tries > u->conf->next_upstream_tries)
&& (!u->peer.unique || u->peer.tries > u->conf->next_upstream_tries))
{
u->peer.tries = u->conf->next_upstream_tries;
}
@ -1287,9 +1289,10 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
ur->ctx = NULL;
u->peer.start_time = ngx_current_msec;
u->peer.unique = u->conf->next_upstream_unique;
if (u->conf->next_upstream_tries
&& u->peer.tries > u->conf->next_upstream_tries)
&& (!u->peer.unique || u->peer.tries > u->conf->next_upstream_tries))
{
u->peer.tries = u->conf->next_upstream_tries;
}
@ -4743,6 +4746,42 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u,
u->peer.connection = NULL;
}
if (u->conf->next_upstream_delay) {
if (u->event == NULL) {
u->event = ngx_pcalloc(r->pool, sizeof(ngx_event_t));
if (u->event == NULL) {
ngx_http_upstream_finalize_request(r, u,
NGX_HTTP_INTERNAL_SERVER_ERROR);
return;
}
u->event->handler = ngx_http_upstream_connect_handler;
u->event->data = r;
u->event->log = r->connection->log;
}
ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
"next http upstream delay %M",
u->conf->next_upstream_delay);
ngx_add_timer(u->event, u->conf->next_upstream_delay);
return;
}
ngx_http_upstream_connect(r, u);
}
static void
ngx_http_upstream_connect_handler(ngx_event_t *ev)
{
ngx_http_request_t *r;
ngx_http_upstream_t *u;
r = ev->data;
u = r->upstream;
ngx_http_upstream_connect(r, u);
}
@ -4840,6 +4879,10 @@ ngx_http_upstream_finalize_request(ngx_http_request_t *r,
u->peer.connection = NULL;
if (u->event && u->event->timer_set) {
ngx_del_timer(u->event);
}
if (u->pipe) {
u->pipe->upstream = NULL;
}

View file

@ -166,6 +166,7 @@ typedef struct {
ngx_msec_t send_timeout;
ngx_msec_t read_timeout;
ngx_msec_t next_upstream_timeout;
ngx_msec_t next_upstream_delay;
size_t send_lowat;
size_t buffer_size;
@ -185,6 +186,7 @@ typedef struct {
ngx_uint_t next_upstream;
ngx_uint_t store_access;
ngx_uint_t next_upstream_tries;
ngx_flag_t next_upstream_unique;
ngx_flag_t buffering;
ngx_flag_t request_buffering;
ngx_flag_t pass_request_headers;
@ -340,6 +342,8 @@ struct ngx_http_upstream_s {
ngx_peer_connection_t peer;
ngx_event_t *event;
ngx_event_pipe_t *pipe;
ngx_chain_t *request_bufs;

View file

@ -713,7 +713,7 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data)
ngx_http_upstream_rr_peers_wlock(peers);
#if (NGX_HTTP_UPSTREAM_ZONE)
if (peers->config && rrp->config != *peers->config) {
if (pc->unique && peers->config && rrp->config != *peers->config) {
goto busy;
}
#endif
@ -919,7 +919,9 @@ best_chosen:
n = p / (8 * sizeof(uintptr_t));
m = (uintptr_t) 1 << p % (8 * sizeof(uintptr_t));
rrp->tried[n] |= m;
if (pc->unique) {
rrp->tried[n] |= m;
}
if (now - best->checked > best->fail_timeout) {
best->checked = now;
@ -1049,7 +1051,13 @@ ngx_http_upstream_free_round_robin_peer_locked(ngx_peer_connection_t *pc,
ngx_http_upstream_rr_peers_unlock(rrp->peers);
pc->tries = 0;
if (pc->unique) {
pc->tries = 0;
} else if (pc->tries) {
pc->tries--;
}
return;
}