diff options
author | Igor Sysoev <igor@sysoev.ru> | 2006-12-04 16:46:13 +0000 |
---|---|---|
committer | Igor Sysoev <igor@sysoev.ru> | 2006-12-04 16:46:13 +0000 |
commit | 3d2fd18a3935a7f1b68f14aa95990eef8841acad (patch) | |
tree | 9b0bc5932393105bf4f89f403d042494762b8ea2 /src/http/modules | |
parent | a53f7293c8b8e2dcc3168ce96903afe5c55dd763 (diff) | |
download | nginx-3d2fd18a3935a7f1b68f14aa95990eef8841acad.tar.gz nginx-3d2fd18a3935a7f1b68f14aa95990eef8841acad.zip |
upstream choice modules
Diffstat (limited to 'src/http/modules')
-rw-r--r-- | src/http/modules/ngx_http_fastcgi_module.c | 81 | ||||
-rw-r--r-- | src/http/modules/ngx_http_memcached_module.c | 81 | ||||
-rw-r--r-- | src/http/modules/ngx_http_proxy_module.c | 79 | ||||
-rw-r--r-- | src/http/modules/ngx_http_upstream_ip_hash_module.c | 228 |
4 files changed, 355 insertions, 114 deletions
diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c index f22de517a..ab214770e 100644 --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -13,9 +13,6 @@ typedef struct { ngx_http_upstream_conf_t upstream; - ngx_http_upstream_srv_conf_t *upstream_peers; - ngx_peers_t *peers0; - ngx_str_t index; ngx_array_t *flushes; @@ -121,6 +118,11 @@ static char *ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); +static char *ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); + static ngx_http_fastcgi_request_start_t ngx_http_fastcgi_request_start = { { 1, /* version */ @@ -310,16 +312,16 @@ static ngx_command_t ngx_http_fastcgi_commands[] = { { ngx_string("fastcgi_upstream_max_fails"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_fastcgi_loc_conf_t, upstream.max_fails), + ngx_http_fastcgi_upstream_max_fails_unsupported, + 0, + 0, NULL }, { ngx_string("fastcgi_upstream_fail_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_sec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_fastcgi_loc_conf_t, upstream.fail_timeout), + ngx_http_fastcgi_upstream_fail_timeout_unsupported, + 0, + 0, NULL }, { ngx_string("fastcgi_param"), @@ -411,8 +413,6 @@ ngx_http_fastcgi_handler(ngx_http_request_t *r) u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; - u->peer.peers = flcf->upstream_peers->peers; - u->peer.tries = flcf->upstream_peers->peers->number; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif @@ -1547,9 +1547,6 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf) conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; - conf->upstream.max_fails = NGX_CONF_UNSET_UINT; - conf->upstream.fail_timeout = NGX_CONF_UNSET; - conf->upstream.pass_request_headers = NGX_CONF_UNSET; conf->upstream.pass_request_body = NGX_CONF_UNSET; @@ -1573,7 +1570,6 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) uintptr_t *code; ngx_str_t *header; ngx_uint_t i, j; - ngx_peer_t *peer; ngx_array_t hide_headers; ngx_keyval_t *src; ngx_hash_key_t *hk; @@ -1707,25 +1703,6 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |NGX_HTTP_UPSTREAM_FT_OFF; } - ngx_conf_merge_uint_value(conf->upstream.max_fails, - prev->upstream.max_fails, 1); - - ngx_conf_merge_sec_value(conf->upstream.fail_timeout, - prev->upstream.fail_timeout, 10); - - if (conf->upstream_peers) { - peer = conf->upstream_peers->peers->peer; - for (i = 0; i < conf->upstream_peers->peers->number; i++) { - ngx_conf_init_uint_value(peer[i].weight, 1); - peer[i].current_weight = peer[i].weight; - ngx_conf_init_uint_value(peer[i].max_fails, - conf->upstream.max_fails); - ngx_conf_init_value(peer[i].fail_timeout, - conf->upstream.fail_timeout); - } - - } - ngx_conf_merge_path_value(conf->upstream.temp_path, prev->upstream.temp_path, NGX_HTTP_FASTCGI_TEMP_PATH, 1, 2, 0, @@ -1844,8 +1821,8 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) peers: - if (conf->upstream_peers == NULL) { - conf->upstream_peers = prev->upstream_peers; + if (conf->upstream.upstream == NULL) { + conf->upstream.upstream = prev->upstream.upstream; conf->upstream.schema = prev->upstream.schema; } @@ -2033,10 +2010,10 @@ ngx_http_fastcgi_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; - u.upstream = 1; + u.no_resolve = 1; - lcf->upstream_peers = ngx_http_upstream_add(cf, &u); - if (lcf->upstream_peers == NULL) { + lcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); + if (lcf->upstream.upstream == NULL) { return NGX_CONF_ERROR; } @@ -2084,3 +2061,29 @@ ngx_http_fastcgi_lowat_check(ngx_conf_t *cf, void *post, void *data) return NGX_CONF_OK; } + + +static char * +ngx_http_fastcgi_upstream_max_fails_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"fastcgi_upstream_max_fails\" is not supported, " + "use the \"max_fails\" parameter of the \"server\" directive ", + "inside the \"upstream\" block"); + + return NGX_CONF_ERROR; +} + + +static char * +ngx_http_fastcgi_upstream_fail_timeout_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"fastcgi_upstream_fail_timeout\" is not supported, " + "use the \"fail_timeout\" parameter of the \"server\" directive ", + "inside the \"upstream\" block"); + + return NGX_CONF_ERROR; +} diff --git a/src/http/modules/ngx_http_memcached_module.c b/src/http/modules/ngx_http_memcached_module.c index 63bda6498..bd8b83716 100644 --- a/src/http/modules/ngx_http_memcached_module.c +++ b/src/http/modules/ngx_http_memcached_module.c @@ -12,7 +12,6 @@ typedef struct { ngx_http_upstream_conf_t upstream; - ngx_peers_t *peers; } ngx_http_memcached_loc_conf_t; @@ -39,6 +38,11 @@ static char *ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, static char *ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf); +static char *ngx_http_memcached_upstream_max_fails_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); +static char *ngx_http_memcached_upstream_fail_timeout_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); + static ngx_conf_bitmask_t ngx_http_memcached_next_upstream_masks[] = { { ngx_string("error"), NGX_HTTP_UPSTREAM_FT_ERROR }, @@ -96,16 +100,16 @@ static ngx_command_t ngx_http_memcached_commands[] = { { ngx_string("memcached_upstream_max_fails"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_memcached_loc_conf_t, upstream.max_fails), + ngx_http_memcached_upstream_max_fails_unsupported, + 0, + 0, NULL }, { ngx_string("memcached_upstream_fail_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_sec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_memcached_loc_conf_t, upstream.fail_timeout), + ngx_http_memcached_upstream_fail_timeout_unsupported, + 0, + 0, NULL }, ngx_null_command @@ -178,8 +182,6 @@ ngx_http_memcached_handler(ngx_http_request_t *r) u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; - u->peer.peers = mlcf->peers; - u->peer.tries = mlcf->peers->number; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif @@ -511,13 +513,8 @@ ngx_http_memcached_create_loc_conf(ngx_conf_t *cf) conf->upstream.buffer_size = NGX_CONF_UNSET_SIZE; - conf->upstream.max_fails = NGX_CONF_UNSET_UINT; - conf->upstream.fail_timeout = NGX_CONF_UNSET; - - /* "fastcgi_cyclic_temp_file" is disabled */ - conf->upstream.cyclic_temp_file = 0; - /* the hardcoded values */ + conf->upstream.cyclic_temp_file = 0; conf->upstream.buffering = 0; conf->upstream.ignore_client_abort = 0; conf->upstream.send_lowat = 0; @@ -540,8 +537,6 @@ ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) ngx_http_memcached_loc_conf_t *prev = parent; ngx_http_memcached_loc_conf_t *conf = child; - ngx_uint_t i; - ngx_conf_merge_msec_value(conf->upstream.connect_timeout, prev->upstream.connect_timeout, 60000); @@ -566,20 +561,6 @@ ngx_http_memcached_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |NGX_HTTP_UPSTREAM_FT_OFF; } - ngx_conf_merge_uint_value(conf->upstream.max_fails, - prev->upstream.max_fails, 1); - - ngx_conf_merge_sec_value(conf->upstream.fail_timeout, - prev->upstream.fail_timeout, 10); - - if (conf->peers && conf->peers->number > 1) { - for (i = 0; i < conf->peers->number; i++) { - conf->peers->peer[i].weight = 1; - conf->peers->peer[i].max_fails = conf->upstream.max_fails; - conf->peers->peer[i].fail_timeout = conf->upstream.fail_timeout; - } - } - return NGX_CONF_OK; } @@ -602,16 +583,14 @@ ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) ngx_memzero(&u, sizeof(ngx_url_t)); u.url = value[1]; - u.uri_part = 1; + u.no_resolve = 1; + /* u.uri_part = 1; may be used as namespace */ - if (ngx_parse_url(cf, &u) != NGX_OK) { - if (u.err) { - ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, - "%s in \"%V\"", u.err, &u.url); - } + lcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); + if (lcf->upstream.upstream == NULL) { + return NGX_CONF_ERROR; } - lcf->peers = u.peers; lcf->upstream.schema.len = sizeof("memcached://") - 1; lcf->upstream.schema.data = (u_char *) "memcached://"; @@ -627,3 +606,29 @@ ngx_http_memcached_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) return NGX_CONF_OK; } + + +static char * +ngx_http_memcached_upstream_max_fails_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"memcached_upstream_max_fails\" is not supported, " + "use the \"max_fails\" parameter of the \"server\" directive ", + "inside the \"upstream\" block"); + + return NGX_CONF_ERROR; +} + + +static char * +ngx_http_memcached_upstream_fail_timeout_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"memcached_upstream_fail_timeout\" is not supported, " + "use the \"fail_timeout\" parameter of the \"server\" directive ", + "inside the \"upstream\" block"); + + return NGX_CONF_ERROR; +} diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c index f17f0a752..2095f6a32 100644 --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -35,8 +35,6 @@ struct ngx_http_proxy_redirect_s { typedef struct { ngx_http_upstream_conf_t upstream; - ngx_http_upstream_srv_conf_t *upstream_peers; - ngx_array_t *flushes; ngx_array_t *body_set_len; ngx_array_t *body_set; @@ -107,6 +105,11 @@ static char *ngx_http_proxy_redirect(ngx_conf_t *cf, ngx_command_t *cmd, static char *ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data); +static char *ngx_http_proxy_upstream_max_fails_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); +static char *ngx_http_proxy_upstream_fail_timeout_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf); + static ngx_conf_post_t ngx_http_proxy_lowat_post = { ngx_http_proxy_lowat_check }; @@ -297,16 +300,16 @@ static ngx_command_t ngx_http_proxy_commands[] = { { ngx_string("proxy_upstream_max_fails"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_num_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, upstream.max_fails), + ngx_http_proxy_upstream_max_fails_unsupported, + 0, + 0, NULL }, { ngx_string("proxy_upstream_fail_timeout"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, - ngx_conf_set_sec_slot, - NGX_HTTP_LOC_CONF_OFFSET, - offsetof(ngx_http_proxy_loc_conf_t, upstream.fail_timeout), + ngx_http_proxy_upstream_fail_timeout_unsupported, + 0, + 0, NULL }, { ngx_string("proxy_pass_header"), @@ -419,8 +422,6 @@ ngx_http_proxy_handler(ngx_http_request_t *r) u->peer.log = r->connection->log; u->peer.log_error = NGX_ERROR_ERR; - u->peer.peers = plcf->upstream_peers->peers; - u->peer.tries = plcf->upstream_peers->peers->number; #if (NGX_THREADS) u->peer.lock = &r->connection->lock; #endif @@ -1498,9 +1499,6 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf) conf->upstream.max_temp_file_size_conf = NGX_CONF_UNSET_SIZE; conf->upstream.temp_file_write_size_conf = NGX_CONF_UNSET_SIZE; - conf->upstream.max_fails = NGX_CONF_UNSET_UINT; - conf->upstream.fail_timeout = NGX_CONF_UNSET; - conf->upstream.pass_request_headers = NGX_CONF_UNSET; conf->upstream.pass_request_body = NGX_CONF_UNSET; @@ -1527,7 +1525,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) uintptr_t *code; ngx_str_t *header; ngx_uint_t i, j; - ngx_peer_t *peer; ngx_array_t hide_headers; ngx_keyval_t *src, *s, *h; ngx_hash_key_t *hk; @@ -1660,24 +1657,6 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) |NGX_HTTP_UPSTREAM_FT_OFF; } - ngx_conf_merge_uint_value(conf->upstream.max_fails, - prev->upstream.max_fails, 1); - - ngx_conf_merge_sec_value(conf->upstream.fail_timeout, - prev->upstream.fail_timeout, 10); - - if (conf->upstream_peers) { - peer = conf->upstream_peers->peers->peer; - for (i = 0; i < conf->upstream_peers->peers->number; i++) { - ngx_conf_init_uint_value(peer[i].weight, 1); - peer[i].current_weight = peer[i].weight; - ngx_conf_init_uint_value(peer[i].max_fails, - conf->upstream.max_fails); - ngx_conf_init_value(peer[i].fail_timeout, - conf->upstream.fail_timeout); - } - } - ngx_conf_merge_path_value(conf->upstream.temp_path, prev->upstream.temp_path, NGX_HTTP_PROXY_TEMP_PATH, 1, 2, 0, @@ -1834,8 +1813,8 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child) peers: - if (conf->upstream_peers == NULL) { - conf->upstream_peers = prev->upstream_peers; + if (conf->upstream.upstream == NULL) { + conf->upstream.upstream = prev->upstream.upstream; conf->host_header = prev->host_header; conf->port_text = prev->port_text; @@ -2180,11 +2159,11 @@ ngx_http_proxy_pass(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) u.url.len = url->len - add; u.url.data = url->data + add; u.default_portn = port; + u.no_resolve = 1; u.uri_part = 1; - u.upstream = 1; - plcf->upstream_peers = ngx_http_upstream_add(cf, &u); - if (plcf->upstream_peers == NULL) { + plcf->upstream.upstream = ngx_http_upstream_add(cf, &u, 0); + if (plcf->upstream.upstream == NULL) { return NGX_CONF_ERROR; } @@ -2345,3 +2324,29 @@ ngx_http_proxy_lowat_check(ngx_conf_t *cf, void *post, void *data) return NGX_CONF_OK; } + + +static char * +ngx_http_proxy_upstream_max_fails_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_upstream_max_fails\" is not supported, " + "use the \"max_fails\" parameter of the \"server\" directive ", + "inside the \"upstream\" block"); + + return NGX_CONF_ERROR; +} + + +static char * +ngx_http_proxy_upstream_fail_timeout_unsupported(ngx_conf_t *cf, + ngx_command_t *cmd, void *conf) +{ + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "\"proxy_upstream_fail_timeout\" is not supported, " + "use the \"fail_timeout\" parameter of the \"server\" directive ", + "inside the \"upstream\" block"); + + return NGX_CONF_ERROR; +} diff --git a/src/http/modules/ngx_http_upstream_ip_hash_module.c b/src/http/modules/ngx_http_upstream_ip_hash_module.c new file mode 100644 index 000000000..1de019e05 --- /dev/null +++ b/src/http/modules/ngx_http_upstream_ip_hash_module.c @@ -0,0 +1,228 @@ + +/* + * Copyright (C) Igor Sysoev + */ + + +#include <ngx_config.h> +#include <ngx_core.h> +#include <ngx_http.h> + + +typedef struct { + /* the round robin data must be first */ + ngx_http_upstream_rr_peer_data_t rrp; + + ngx_uint_t hash; + + /* AF_INET only */ + u_char addr[3]; + + u_char tries; + + ngx_event_get_peer_pt get_rr_peer; +} ngx_http_upstream_ip_hash_peer_data_t; + + +static ngx_int_t ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us); +static ngx_int_t ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, + void *data); +static char *ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, + void *conf); + + +static ngx_command_t ngx_http_upstream_ip_hash_commands[] = { + + { ngx_string("ip_hash"), + NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS, + ngx_http_upstream_ip_hash, + 0, + 0, + NULL }, + + ngx_null_command +}; + + +static ngx_http_module_t ngx_http_upstream_ip_hash_module_ctx = { + NULL, /* preconfiguration */ + NULL, /* postconfiguration */ + + NULL, /* create main configuration */ + NULL, /* init main configuration */ + + NULL, /* create server configuration */ + NULL, /* merge server configuration */ + + NULL, /* create location configuration */ + NULL /* merge location configuration */ +}; + + +ngx_module_t ngx_http_upstream_ip_hash_module = { + NGX_MODULE_V1, + &ngx_http_upstream_ip_hash_module_ctx, /* module context */ + ngx_http_upstream_ip_hash_commands, /* module directives */ + NGX_HTTP_MODULE, /* module type */ + NULL, /* init master */ + NULL, /* init module */ + NULL, /* init process */ + NULL, /* init thread */ + NULL, /* exit thread */ + NULL, /* exit process */ + NULL, /* exit master */ + NGX_MODULE_V1_PADDING +}; + + +ngx_int_t +ngx_http_upstream_init_ip_hash(ngx_conf_t *cf, ngx_http_upstream_srv_conf_t *us) +{ + if (ngx_http_upstream_init_round_robin(cf, us) != NGX_OK) { + return NGX_ERROR; + } + + us->peer.init = ngx_http_upstream_init_ip_hash_peer; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_init_ip_hash_peer(ngx_http_request_t *r, + ngx_http_upstream_srv_conf_t *us) +{ + struct sockaddr_in *sin; + ngx_http_upstream_ip_hash_peer_data_t *iphp; + + iphp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_ip_hash_peer_data_t)); + if (iphp == NULL) { + return NGX_ERROR; + } + + r->upstream->peer.data = &iphp->rrp; + + if (ngx_http_upstream_init_round_robin_peer(r, us) != NGX_OK) { + return NGX_ERROR; + } + + r->upstream->peer.get = ngx_http_upstream_get_ip_hash_peer; + + /* AF_INET only */ + sin = (struct sockaddr_in *) r->connection->sockaddr; + iphp->addr[0] = (u_char) ((sin->sin_addr.s_addr >> 24) & 0xff); + iphp->addr[1] = (u_char) ((sin->sin_addr.s_addr >> 16) & 0xff); + iphp->addr[2] = (u_char) ((sin->sin_addr.s_addr >> 8) & 0xff); + + iphp->hash = 89; + iphp->tries = 0; + iphp->get_rr_peer = ngx_http_upstream_get_round_robin_peer; + + return NGX_OK; +} + + +static ngx_int_t +ngx_http_upstream_get_ip_hash_peer(ngx_peer_connection_t *pc, void *data) +{ + ngx_http_upstream_ip_hash_peer_data_t *iphp = data; + + time_t now; + uintptr_t m; + ngx_uint_t i, n, p, hash; + ngx_http_upstream_rr_peer_t *peer; + + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "get ip hash peer, try: %ui", pc->tries); + + /* TODO: cached */ + + if (iphp->tries > 20 || iphp->rrp.peers->number == 1) { + return iphp->get_rr_peer(pc, &iphp->rrp); + } + + now = ngx_time(); + + pc->cached = 0; + pc->connection = NULL; + + hash = iphp->hash; + + for ( ;; ) { + + for (i = 0; i < 3; i++) { + hash = (hash * 113 + iphp->addr[i]) % 6271; + } + + p = hash % iphp->rrp.peers->number; + + n = p / (8 * sizeof(uintptr_t)); + m = 1 << p % (8 * sizeof(uintptr_t)); + + if (!(iphp->rrp.tried[n] & m)) { + + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, pc->log, 0, + "get ip hash peer, hash: %ui %04XA", p, m); + + peer = &iphp->rrp.peers->peer[p]; + + /* ngx_lock_mutex(iphp->rrp.peers->mutex); */ + + if (!peer->down) { + + if (peer->max_fails == 0 || peer->fails < peer->max_fails) { + break; + } + + if (now - peer->accessed > peer->fail_timeout) { + peer->fails = 0; + break; + } + + } else { + iphp->rrp.tried[n] |= m; + } + + /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */ + + pc->tries--; + } + + if (++iphp->tries >= 20) { + return iphp->get_rr_peer(pc, &iphp->rrp); + } + } + + pc->sockaddr = peer->sockaddr; + pc->socklen = peer->socklen; + pc->name = &peer->name; +#if (NGX_SSL) + pc->ssl_session = peer->ssl_session; +#endif + + /* ngx_unlock_mutex(iphp->rrp.peers->mutex); */ + + iphp->rrp.tried[n] |= m; + iphp->hash = hash; + + return NGX_OK; +} + + +static char * +ngx_http_upstream_ip_hash(ngx_conf_t *cf, ngx_command_t *cmd, void *conf) +{ + ngx_http_upstream_srv_conf_t *uscf; + + uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module); + + uscf->peer.init_upstream = ngx_http_upstream_init_ip_hash; + + uscf->flags = NGX_HTTP_UPSTREAM_CREATE + |NGX_HTTP_UPSTREAM_MAX_FAILS + |NGX_HTTP_UPSTREAM_FAIL_TIMEOUT + |NGX_HTTP_UPSTREAM_DOWN; + + return NGX_CONF_OK; +} |