Created
October 21, 2016 07:37
-
-
Save hfm/c6228dc7d86d5e5e81769d36ad0ee779 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/src/http/modules/ngx_http_upstream_hash_module.c b/src/http/modules/ngx_http_upstream_hash_module.c | |
index 1e2e05c..6c28c64 100644 | |
--- a/src/http/modules/ngx_http_upstream_hash_module.c | |
+++ b/src/http/modules/ngx_http_upstream_hash_module.c | |
@@ -242,6 +242,10 @@ ngx_http_upstream_get_hash_peer(ngx_peer_connection_t *pc, void *data) | |
goto next; | |
} | |
+ if (peer->max_conns && peer->conns >= peer->max_conns) { | |
+ goto next; | |
+ } | |
+ | |
break; | |
next: | |
@@ -523,7 +527,6 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) | |
peer; | |
peer = peer->next, i++) | |
{ | |
- | |
n = i / (8 * sizeof(uintptr_t)); | |
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); | |
@@ -549,6 +552,10 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) | |
continue; | |
} | |
+ if (peer->max_conns && peer->conns >= peer->max_conns) { | |
+ continue; | |
+ } | |
+ | |
peer->current_weight += peer->effective_weight; | |
total += peer->effective_weight; | |
@@ -571,6 +578,7 @@ ngx_http_upstream_get_chash_peer(ngx_peer_connection_t *pc, void *data) | |
hp->tries++; | |
if (hp->tries >= points->number) { | |
+ pc->name = hp->rrp.peers->name; | |
ngx_http_upstream_rr_peers_unlock(hp->rrp.peers); | |
return NGX_BUSY; | |
} | |
@@ -647,6 +655,7 @@ ngx_http_upstream_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
uscf->flags = NGX_HTTP_UPSTREAM_CREATE | |
|NGX_HTTP_UPSTREAM_WEIGHT | |
+ |NGX_HTTP_UPSTREAM_MAX_CONNS | |
|NGX_HTTP_UPSTREAM_MAX_FAILS | |
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | |
|NGX_HTTP_UPSTREAM_DOWN; | |
diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c | |
index 8a5f0fa..296108f 100644 | |
--- a/src/http/modules/ngx_http_upstream_ip_hash_module.c | |
+++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c | |
@@ -212,6 +212,10 @@ ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) | |
goto next; | |
} | |
+ if (peer->max_conns && peer->conns >= peer->max_conns) { | |
+ goto next; | |
+ } | |
+ | |
break; | |
next: | |
@@ -259,6 +263,7 @@ ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
uscf->flags = NGX_HTTP_UPSTREAM_CREATE | |
|NGX_HTTP_UPSTREAM_WEIGHT | |
+ |NGX_HTTP_UPSTREAM_MAX_CONNS | |
|NGX_HTTP_UPSTREAM_MAX_FAILS | |
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | |
|NGX_HTTP_UPSTREAM_DOWN; | |
diff --git a/src/http/modules/ngx_http_upstream_least_conn_module.c b/src/http/modules/ngx_http_upstream_least_conn_module.c | |
index 8a300c1..ebe0627 100644 | |
--- a/src/http/modules/ngx_http_upstream_least_conn_module.c | |
+++ b/src/http/modules/ngx_http_upstream_least_conn_module.c | |
@@ -136,7 +136,6 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data) | |
peer; | |
peer = peer->next, i++) | |
{ | |
- | |
n = i / (8 * sizeof(uintptr_t)); | |
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); | |
@@ -155,6 +154,10 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data) | |
continue; | |
} | |
+ if (peer->max_conns && peer->conns >= peer->max_conns) { | |
+ continue; | |
+ } | |
+ | |
/* | |
* select peer with least number of connections; if there are | |
* multiple peers with the same number of connections, select | |
@@ -210,6 +213,10 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data) | |
continue; | |
} | |
+ if (peer->max_conns && peer->conns >= peer->max_conns) { | |
+ continue; | |
+ } | |
+ | |
peer->current_weight += peer->effective_weight; | |
total += peer->effective_weight; | |
@@ -273,12 +280,6 @@ ngx_http_upstream_get_least_conn_peer(ngx_peer_connection_t *pc, void *data) | |
ngx_http_upstream_rr_peers_wlock(peers); | |
} | |
- /* all peers failed, mark them as live for quick recovery */ | |
- | |
- for (peer = peers->peer; peer; peer = peer->next) { | |
- peer->fails = 0; | |
- } | |
- | |
ngx_http_upstream_rr_peers_unlock(peers); | |
pc->name = peers->name; | |
@@ -303,6 +304,7 @@ ngx_http_upstream_least_conn(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
uscf->flags = NGX_HTTP_UPSTREAM_CREATE | |
|NGX_HTTP_UPSTREAM_WEIGHT | |
+ |NGX_HTTP_UPSTREAM_MAX_CONNS | |
|NGX_HTTP_UPSTREAM_MAX_FAILS | |
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | |
|NGX_HTTP_UPSTREAM_DOWN | |
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c | |
index 7e4b3c5..ceb798f 100644 | |
--- a/src/http/ngx_http_upstream.c | |
+++ b/src/http/ngx_http_upstream.c | |
@@ -748,6 +748,8 @@ ngx_http_upstream_init_request(ngx_http_request_t *r) | |
return; | |
} | |
+ u->upstream = uscf; | |
+ | |
#if (NGX_HTTP_SSL) | |
u->ssl_name = uscf->host; | |
#endif | |
@@ -5442,6 +5444,7 @@ ngx_http_upstream(ngx_conf_t *cf, ngx_command_t *cmd, void *dummy) | |
uscf = ngx_http_upstream_add(cf, &u, NGX_HTTP_UPSTREAM_CREATE | |
|NGX_HTTP_UPSTREAM_WEIGHT | |
+ |NGX_HTTP_UPSTREAM_MAX_CONNS | |
|NGX_HTTP_UPSTREAM_MAX_FAILS | |
|NGX_HTTP_UPSTREAM_FAIL_TIMEOUT | |
|NGX_HTTP_UPSTREAM_DOWN | |
@@ -5543,7 +5546,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
time_t fail_timeout; | |
ngx_str_t *value, s; | |
ngx_url_t u; | |
- ngx_int_t weight, max_fails; | |
+ ngx_int_t weight, max_conns, max_fails; | |
ngx_uint_t i; | |
ngx_http_upstream_server_t *us; | |
@@ -5557,6 +5560,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
value = cf->args->elts; | |
weight = 1; | |
+ max_conns = 0; | |
max_fails = 1; | |
fail_timeout = 10; | |
@@ -5577,6 +5581,21 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
continue; | |
} | |
+ if (ngx_strncmp(value[i].data, "max_conns=", 10) == 0) { | |
+ | |
+ if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_CONNS)) { | |
+ goto not_supported; | |
+ } | |
+ | |
+ max_conns = ngx_atoi(&value[i].data[10], value[i].len - 10); | |
+ | |
+ if (max_conns == NGX_ERROR) { | |
+ goto invalid; | |
+ } | |
+ | |
+ continue; | |
+ } | |
+ | |
if (ngx_strncmp(value[i].data, "max_fails=", 10) == 0) { | |
if (!(uscf->flags & NGX_HTTP_UPSTREAM_MAX_FAILS)) { | |
@@ -5653,6 +5672,7 @@ ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) | |
us->addrs = u.addrs; | |
us->naddrs = u.naddrs; | |
us->weight = weight; | |
+ us->max_conns = max_conns; | |
us->max_fails = max_fails; | |
us->fail_timeout = fail_timeout; | |
@@ -5717,14 +5737,14 @@ ngx_http_upstream_add(ngx_conf_t *cf, ngx_url_t *u, ngx_uint_t flags) | |
} | |
if ((uscfp[i]->flags & NGX_HTTP_UPSTREAM_CREATE) && !u->no_port) { | |
- ngx_conf_log_error(NGX_LOG_WARN, cf, 0, | |
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, | |
"upstream \"%V\" may not have port %d", | |
&u->host, u->port); | |
return NULL; | |
} | |
if ((flags & NGX_HTTP_UPSTREAM_CREATE) && !uscfp[i]->no_port) { | |
- ngx_log_error(NGX_LOG_WARN, cf->log, 0, | |
+ ngx_log_error(NGX_LOG_EMERG, cf->log, 0, | |
"upstream \"%V\" may not have port %d in %s:%ui", | |
&u->host, uscfp[i]->port, | |
uscfp[i]->file_name, uscfp[i]->line); | |
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h | |
index ef861f4..3d521f2 100644 | |
--- a/src/http/ngx_http_upstream.h | |
+++ b/src/http/ngx_http_upstream.h | |
@@ -95,11 +95,16 @@ typedef struct { | |
ngx_addr_t *addrs; | |
ngx_uint_t naddrs; | |
ngx_uint_t weight; | |
+ ngx_uint_t max_conns; | |
ngx_uint_t max_fails; | |
time_t fail_timeout; | |
+ ngx_msec_t slow_start; | |
unsigned down:1; | |
unsigned backup:1; | |
+ | |
+ NGX_COMPAT_BEGIN(6) | |
+ NGX_COMPAT_END | |
} ngx_http_upstream_server_t; | |
@@ -109,6 +114,7 @@ typedef struct { | |
#define NGX_HTTP_UPSTREAM_FAIL_TIMEOUT 0x0008 | |
#define NGX_HTTP_UPSTREAM_DOWN 0x0010 | |
#define NGX_HTTP_UPSTREAM_BACKUP 0x0020 | |
+#define NGX_HTTP_UPSTREAM_MAX_CONNS 0x0100 | |
struct ngx_http_upstream_srv_conf_s { | |
@@ -202,6 +208,7 @@ typedef struct { | |
ngx_array_t *cache_valid; | |
ngx_array_t *cache_bypass; | |
+ ngx_array_t *cache_purge; | |
ngx_array_t *no_cache; | |
#endif | |
@@ -215,7 +222,7 @@ typedef struct { | |
unsigned intercept_404:1; | |
unsigned change_buffering:1; | |
-#if (NGX_HTTP_SSL) | |
+#if (NGX_HTTP_SSL || NGX_COMPAT) | |
ngx_ssl_t *ssl; | |
ngx_flag_t ssl_session_reuse; | |
@@ -225,6 +232,9 @@ typedef struct { | |
#endif | |
ngx_str_t module; | |
+ | |
+ NGX_COMPAT_BEGIN(2) | |
+ NGX_COMPAT_END | |
} ngx_http_upstream_conf_t; | |
@@ -313,6 +323,7 @@ struct ngx_http_upstream_s { | |
ngx_chain_writer_ctx_t writer; | |
ngx_http_upstream_conf_t *conf; | |
+ ngx_http_upstream_srv_conf_t *upstream; | |
#if (NGX_HTTP_CACHE) | |
ngx_array_t *caches; | |
#endif | |
@@ -356,7 +367,7 @@ struct ngx_http_upstream_s { | |
ngx_str_t schema; | |
ngx_str_t uri; | |
-#if (NGX_HTTP_SSL) | |
+#if (NGX_HTTP_SSL || NGX_COMPAT) | |
ngx_str_t ssl_name; | |
#endif | |
@@ -377,6 +388,9 @@ struct ngx_http_upstream_s { | |
unsigned request_sent:1; | |
unsigned request_body_sent:1; | |
unsigned header_sent:1; | |
+ | |
+ NGX_COMPAT_BEGIN(1) | |
+ NGX_COMPAT_END | |
}; | |
diff --git a/src/http/ngx_http_upstream_round_robin.c b/src/http/ngx_http_upstream_round_robin.c | |
index 8479c42..0137bf6 100644 | |
--- a/src/http/ngx_http_upstream_round_robin.c | |
+++ b/src/http/ngx_http_upstream_round_robin.c | |
@@ -92,6 +92,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, | |
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; | |
@@ -155,6 +156,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, | |
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; | |
@@ -223,6 +225,7 @@ ngx_http_upstream_init_round_robin(ngx_conf_t *cf, | |
peer[i].weight = 1; | |
peer[i].effective_weight = 1; | |
peer[i].current_weight = 0; | |
+ peer[i].max_conns = 0; | |
peer[i].max_fails = 1; | |
peer[i].fail_timeout = 10; | |
*peerp = &peer[i]; | |
@@ -257,6 +260,7 @@ ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r, | |
rrp->peers = us->peer.data; | |
rrp->current = NULL; | |
+ rrp->config = 0; | |
n = rrp->peers->number; | |
@@ -337,6 +341,7 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, | |
peer[0].weight = 1; | |
peer[0].effective_weight = 1; | |
peer[0].current_weight = 0; | |
+ peer[0].max_conns = 0; | |
peer[0].max_fails = 1; | |
peer[0].fail_timeout = 10; | |
peers->peer = peer; | |
@@ -370,6 +375,7 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, | |
peer[i].weight = 1; | |
peer[i].effective_weight = 1; | |
peer[i].current_weight = 0; | |
+ peer[i].max_conns = 0; | |
peer[i].max_fails = 1; | |
peer[i].fail_timeout = 10; | |
*peerp = &peer[i]; | |
@@ -379,6 +385,7 @@ ngx_http_upstream_create_round_robin_peer(ngx_http_request_t *r, | |
rrp->peers = peers; | |
rrp->current = NULL; | |
+ rrp->config = 0; | |
if (rrp->peers->number <= 8 * sizeof(uintptr_t)) { | |
rrp->tried = &rrp->data; | |
@@ -432,6 +439,10 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) | |
goto failed; | |
} | |
+ if (peer->max_conns && peer->conns >= peer->max_conns) { | |
+ goto failed; | |
+ } | |
+ | |
rrp->current = peer; | |
} else { | |
@@ -485,12 +496,6 @@ ngx_http_upstream_get_round_robin_peer(ngx_peer_connection_t *pc, void *data) | |
ngx_http_upstream_rr_peers_wlock(peers); | |
} | |
- /* all peers failed, mark them as live for quick recovery */ | |
- | |
- for (peer = peers->peer; peer; peer = peer->next) { | |
- peer->fails = 0; | |
- } | |
- | |
ngx_http_upstream_rr_peers_unlock(peers); | |
pc->name = peers->name; | |
@@ -521,7 +526,6 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp) | |
peer; | |
peer = peer->next, i++) | |
{ | |
- | |
n = i / (8 * sizeof(uintptr_t)); | |
m = (uintptr_t) 1 << i % (8 * sizeof(uintptr_t)); | |
@@ -540,6 +544,10 @@ ngx_http_upstream_get_peer(ngx_http_upstream_rr_peer_data_t *rrp) | |
continue; | |
} | |
+ if (peer->max_conns && peer->conns >= peer->max_conns) { | |
+ continue; | |
+ } | |
+ | |
peer->current_weight += peer->effective_weight; | |
total += peer->effective_weight; | |
diff --git a/src/http/ngx_http_upstream_round_robin.h b/src/http/ngx_http_upstream_round_robin.h | |
index f2c573f..45f258d 100644 | |
--- a/src/http/ngx_http_upstream_round_robin.h | |
+++ b/src/http/ngx_http_upstream_round_robin.h | |
@@ -27,6 +27,7 @@ struct ngx_http_upstream_rr_peer_s { | |
ngx_int_t weight; | |
ngx_uint_t conns; | |
+ ngx_uint_t max_conns; | |
ngx_uint_t fails; | |
time_t accessed; | |
@@ -34,19 +35,24 @@ struct ngx_http_upstream_rr_peer_s { | |
ngx_uint_t max_fails; | |
time_t fail_timeout; | |
+ ngx_msec_t slow_start; | |
+ ngx_msec_t start_time; | |
- ngx_uint_t down; /* unsigned down:1; */ | |
+ ngx_uint_t down; | |
-#if (NGX_HTTP_SSL) | |
+#if (NGX_HTTP_SSL || NGX_COMPAT) | |
void *ssl_session; | |
int ssl_session_len; | |
#endif | |
- ngx_http_upstream_rr_peer_t *next; | |
- | |
#if (NGX_HTTP_UPSTREAM_ZONE) | |
ngx_atomic_t lock; | |
#endif | |
+ | |
+ ngx_http_upstream_rr_peer_t *next; | |
+ | |
+ NGX_COMPAT_BEGIN(32) | |
+ NGX_COMPAT_END | |
}; | |
@@ -119,6 +125,7 @@ struct ngx_http_upstream_rr_peers_s { | |
typedef struct { | |
+ ngx_uint_t config; | |
ngx_http_upstream_rr_peers_t *peers; | |
ngx_http_upstream_rr_peer_t *current; | |
uintptr_t *tried; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment