Welcome! Log In Create A New Profile

Advanced

[PATCH]upstream server directive support variable

June 01, 2013 09:38PM
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;

_______________________________________________
nginx-devel mailing list
nginx-devel@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-devel
Subject Author Views Posted

[PATCH]upstream server directive support variable Attachments

flygoast 1142 June 01, 2013 09:38PM

Re: [PATCH]upstream server directive support variable

Maxim Dounin 462 June 02, 2013 07:34AM

Re:Re: [PATCH]upstream server directive support variable

flygoast 515 June 02, 2013 08:48AM

Re: Re: [PATCH]upstream server directive support variable

Maxim Dounin 463 June 02, 2013 12:24PM



Sorry, you do not have permission to post/reply in this forum.

Online Users

Guests: 168
Record Number of Users: 8 on April 13, 2023
Record Number of Guests: 421 on December 02, 2018
Powered by nginx      Powered by FreeBSD      PHP Powered      Powered by MariaDB      ipv6 ready