[PATCH]upstream server directive support variable
flygoast
flygoast at 126.com
Sun Jun 2 01:34:58 UTC 2013
Hi, guys
In my business, I need dynamicly to find the backend ip address according to the request. However, I also want to use the upstream to take advantage of load balance. So I add the variable support in server directive. For sake of avoiding blocking the whole worker due to resolving domain, at present, only dotted decimal IP address should be parsed in
the variables. Anyone can help to check or improve it? Thanks.
The patch is based on 1.2.7.
diff -ruNp nginx-1.2.7/src/http/ngx_http_upstream.c nginx-1.2.7.m/src/http/ngx_http_upstream.c
--- nginx-1.2.7/src/http/ngx_http_upstream.c2013-02-11 22:39:49.000000000 +0800
+++ nginx-1.2.7.m/src/http/ngx_http_upstream.c2013-05-27 20:33:17.000000000 +0800
@@ -4220,8 +4220,9 @@ ngx_http_upstream_server(ngx_conf_t *cf,
ngx_str_t *value, s;
ngx_url_t u;
ngx_int_t weight, max_fails;
- ngx_uint_t i;
+ ngx_uint_t i, n;
ngx_http_upstream_server_t *us;
+ ngx_http_script_compile_t sc;
if (uscf->servers == NULL) {
uscf->servers = ngx_array_create(cf->pool, 4,
@@ -4245,13 +4246,32 @@ ngx_http_upstream_server(ngx_conf_t *cf,
u.url = value[1];
u.default_port = 80;
- if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
- if (u.err) {
- ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
- "%s in upstream \"%V\"", u.err, &u.url);
+ n = ngx_http_script_variables_count(&value[1]);
+
+ if (n) {
+ ngx_memzero(&sc, sizeof(ngx_http_script_compile_t));
+
+ sc.cf = cf;
+ sc.source = &value[1];
+ sc.lengths = &us->proxy_lengths;
+ sc.values = &us->proxy_values;
+ sc.variables = n;
+ sc.complete_lengths = 1;
+ sc.complete_values = 1;
+
+ if (ngx_http_script_compile(&sc) != NGX_OK) {
+ return NGX_CONF_ERROR;
}
- return NGX_CONF_ERROR;
+ } else {
+ if (ngx_parse_url(cf->pool, &u) != NGX_OK) {
+ if (u.err) {
+ ngx_conf_log_error(NGX_LOG_EMERG, cf, 0,
+ "%s in upstream \"%V\"", u.err, &u.url);
+ }
+
+ return NGX_CONF_ERROR;
+ }
}
weight = 1;
@@ -4333,8 +4353,15 @@ ngx_http_upstream_server(ngx_conf_t *cf,
goto invalid;
}
- us->addrs = u.addrs;
- us->naddrs = u.naddrs;
+ if (n) {
+ us->addrs = NULL;
+ us->naddrs = 1;
+
+ } else {
+ us->addrs = u.addrs;
+ us->naddrs = u.naddrs;
+ }
+
us->weight = weight;
us->max_fails = max_fails;
us->fail_timeout = fail_timeout;
diff -ruNp nginx-1.2.7/src/http/ngx_http_upstream.h nginx-1.2.7.m/src/http/ngx_http_upstream.h
--- nginx-1.2.7/src/http/ngx_http_upstream.h2012-02-13 19:01:58.000000000 +0800
+++ nginx-1.2.7.m/src/http/ngx_http_upstream.h2013-05-27 20:38:58.000000000 +0800
@@ -91,6 +91,9 @@ typedef struct {
ngx_uint_t max_fails;
time_t fail_timeout;
+ ngx_array_t *proxy_lengths;
+ ngx_array_t *proxy_values;
+
unsigned down:1;
unsigned backup:1;
} ngx_http_upstream_server_t;
@@ -116,6 +119,8 @@ struct ngx_http_upstream_srv_conf_s {
ngx_uint_t line;
in_port_t port;
in_port_t default_port;
+ ngx_uint_t variable_peer;
+ ngx_uint_t variable_backup;
};
diff -ruNp nginx-1.2.7/src/http/ngx_http_upstream_round_robin.c nginx-1.2.7.m/src/http/ngx_http_upstream_round_robin.c
--- nginx-1.2.7/src/http/ngx_http_upstream_round_robin.c2013-02-11 22:56:14.000000000 +0800
+++ nginx-1.2.7.m/src/http/ngx_http_upstream_round_robin.c2013-05-27 20:59:49.000000000 +0800
@@ -78,9 +78,19 @@ ngx_http_upstream_init_round_robin(ngx_c
continue;
}
- peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
- peers->peer[n].socklen = server[i].addrs[j].socklen;
- peers->peer[n].name = server[i].addrs[j].name;
+ if (server[i].addrs == NULL) {
+ us->variable_peer++;
+ peers->peer[n].sockaddr = NULL;
+ peers->peer[n].socklen = 0;
+ ngx_str_null(&peers->peer[n].name);
+ peers->peer[n].server = &server[i];
+
+ } else {
+ peers->peer[n].sockaddr = server[i].addrs[j].sockaddr;
+ peers->peer[n].socklen = server[i].addrs[j].socklen;
+ peers->peer[n].name = server[i].addrs[j].name;
+ }
+
peers->peer[n].max_fails = server[i].max_fails;
peers->peer[n].fail_timeout = server[i].fail_timeout;
peers->peer[n].down = server[i].down;
@@ -136,9 +146,20 @@ ngx_http_upstream_init_round_robin(ngx_c
continue;
}
- backup->peer[n].sockaddr = server[i].addrs[j].sockaddr;
- backup->peer[n].socklen = server[i].addrs[j].socklen;
- backup->peer[n].name = server[i].addrs[j].name;
+ if (server[i].addrs == NULL) {
+ us->variable_backup++;
+ backup->peer[n].sockaddr = NULL;
+ backup->peer[n].socklen = 0;
+ ngx_str_null(&backup->peer[n].name);
+ backup->peer[n].server = &server[i];
+
+ } else {
+
+ backup->peer[n].sockaddr = server[i].addrs[j].sockaddr;
+ backup->peer[n].socklen = server[i].addrs[j].socklen;
+ backup->peer[n].name = server[i].addrs[j].name;
+ }
+
backup->peer[n].weight = server[i].weight;
backup->peer[n].effective_weight = server[i].weight;
backup->peer[n].current_weight = 0;
@@ -228,6 +249,73 @@ ngx_http_upstream_cmp_servers(const void
}
+static ngx_int_t
+ngx_http_upstream_get_round_robin_variable_peer(ngx_http_request_t *r,
+ ngx_http_upstream_rr_peers_t *peers, ngx_uint_t variable_cnt)
+{
+ ngx_uint_t i, j, n;
+ ngx_url_t url;
+ ngx_http_upstream_rr_peer_t *peer;
+
+ n = peers->number;
+
+ for (i = 0, j = 0; j < variable_cnt && i < n; i++) {
+
+ peer = &peers->peer[i];
+
+ if (peer->server) {
+
+ peer->sockaddr = NULL;
+ peer->socklen = 0;
+ ngx_str_null(&peer->name);
+
+ if (ngx_http_script_run(r, &peer->name,
+ peer->server->proxy_lengths->elts, 0,
+ peer->server->proxy_values->elts)
+ == NULL)
+ {
+ return NGX_ERROR;
+ }
+
+ ngx_memzero(&url, sizeof(ngx_url_t));
+ url.url = peer->name;
+ url.default_port = 80;
+ url.no_resolve = 1;
+
+ if (ngx_parse_url(r->pool, &url) != NGX_OK) {
+ if (url.err) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "%s in upstream \"%V\"", url.err, &url.url);
+ }
+
+ return NGX_ERROR;
+ }
+
+ url.one_addr = 1;
+ if (url.no_port) {
+ url.port = url.default_port;
+ }
+
+ if (ngx_inet_resolve_host(r->pool, &url) != NGX_OK) {
+ if (url.err) {
+ ngx_log_error(NGX_LOG_ERR, r->connection->log, 0,
+ "%s in upstream \"%V\"", url.err, &url.url);
+ }
+
+ return NGX_ERROR;
+ }
+
+ peer->sockaddr = url.addrs[0].sockaddr;
+ peer->socklen = url.addrs[0].socklen;
+
+ j++;
+ }
+ }
+
+ return NGX_OK;
+}
+
+
ngx_int_t
ngx_http_upstream_init_round_robin_peer(ngx_http_request_t *r,
ngx_http_upstream_srv_conf_t *us)
@@ -251,6 +339,25 @@ ngx_http_upstream_init_round_robin_peer(
n = rrp->peers->number;
+ if (us->variable_peer > 0) {
+ if (ngx_http_upstream_get_round_robin_variable_peer(r, rrp->peers,
+ us->variable_peer)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+ }
+
+ if (us->variable_backup > 0) {
+ if (ngx_http_upstream_get_round_robin_variable_peer(r,
+ rrp->peers->next,
+ us->variable_backup)
+ == NGX_ERROR)
+ {
+ return NGX_ERROR;
+ }
+ }
+
if (rrp->peers->next && rrp->peers->next->number > n) {
n = rrp->peers->next->number;
}
diff -ruNp nginx-1.2.7/src/http/ngx_http_upstream_round_robin.h nginx-1.2.7.m/src/http/ngx_http_upstream_round_robin.h
--- nginx-1.2.7/src/http/ngx_http_upstream_round_robin.h2012-07-03 00:41:13.000000000 +0800
+++ nginx-1.2.7.m/src/http/ngx_http_upstream_round_robin.h2013-05-24 13:57:52.000000000 +0800
@@ -18,6 +18,7 @@ typedef struct {
struct sockaddr *sockaddr;
socklen_t socklen;
ngx_str_t name;
+ ngx_http_upstream_server_t *server;
ngx_int_t current_weight;
ngx_int_t effective_weight;
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20130602/c7594ec5/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: nginx-1.2.7-upstream.patch
Type: application/octet-stream
Size: 9256 bytes
Desc: not available
URL: <http://mailman.nginx.org/pipermail/nginx-devel/attachments/20130602/c7594ec5/attachment-0001.obj>
More information about the nginx-devel
mailing list