Mercurial > hg > ngx_http_upstream_keepalive
diff ngx_http_upstream_keepalive_module.c @ 6:bef88ba0b378
Keepalive: distinguish between upstream servers by default.
Option 'single' may be used if single pool of connections desired for some
reason.
author | Maxim Dounin <mdounin@mdounin.ru> |
---|---|
date | Fri, 24 Oct 2008 02:03:39 +0400 |
parents | e7d1b49e0611 |
children | 565939797f5c |
line wrap: on
line diff
--- a/ngx_http_upstream_keepalive_module.c +++ b/ngx_http_upstream_keepalive_module.c @@ -12,11 +12,16 @@ typedef struct { ngx_queue_t queue; ngx_connection_t *connection; + + socklen_t socklen; + struct sockaddr_storage sockaddr; + } ngx_http_upstream_keepalive_cache_t; typedef struct { ngx_uint_t max_cached; + ngx_uint_t single; /* unsigned:1 */ ngx_queue_t cache; ngx_queue_t free; @@ -56,7 +61,7 @@ static char *ngx_http_upstream_keepalive static ngx_command_t ngx_http_upstream_keepalive_commands[] = { { ngx_string("keepalive"), - NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS|NGX_CONF_TAKE1, + NGX_HTTP_UPS_CONF|NGX_CONF_TAKE12, ngx_http_upstream_keepalive, 0, 0, @@ -179,15 +184,16 @@ ngx_http_upstream_get_keepalive_peer(ngx ngx_http_upstream_keepalive_peer_data_t *kp = data; ngx_http_upstream_keepalive_cache_t *item; - ngx_queue_t *q; + ngx_int_t rc; + ngx_queue_t *q, *cache; ngx_connection_t *c; ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0, "get keepalive peer"); - /* XXX single pool of cached connections */ + /* single pool of cached connections */ - if (!ngx_queue_empty(&kp->conf->cache)) { + if (kp->conf->single && !ngx_queue_empty(&kp->conf->cache)) { q = ngx_queue_head(&kp->conf->cache); ngx_queue_remove(q); @@ -208,7 +214,43 @@ ngx_http_upstream_get_keepalive_peer(ngx return NGX_DONE; } - return kp->original_get_peer(pc, kp->data); + rc = kp->original_get_peer(pc, kp->data); + + if (kp->conf->single || rc != NGX_OK) { + return rc; + } + + /* search cache for suitable connection */ + + cache = &kp->conf->cache; + + for (q = ngx_queue_head(cache); + q != ngx_queue_sentinel(cache); + q = ngx_queue_next(q)) + { + item = ngx_queue_data(q, ngx_http_upstream_keepalive_cache_t, queue); + c = item->connection; + + if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr, + item->socklen, pc->socklen) + == 0) + { + ngx_queue_remove(q); + ngx_queue_insert_head(&kp->conf->free, q); + + c->idle = 0; + c->log = pc->log; + c->read->log = pc->log; + c->write->log = pc->log; + + pc->connection = c; + pc->cached = 1; + + return NGX_DONE; + } + } + + return NGX_OK; } @@ -268,6 +310,9 @@ ngx_http_upstream_free_keepalive_peer(ng c->log = ngx_cycle->log; c->read->log = ngx_cycle->log; c->write->log = ngx_cycle->log; + + item->socklen = pc->socklen; + ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen); } return kp->original_free_peer(pc, kp->data, state); @@ -367,16 +412,22 @@ ngx_http_upstream_keepalive(ngx_conf_t * value = cf->args->elts; - for (i = 1; i < cf->args->nelts; i++) { - - if (ngx_strncmp(value[i].data, "cached=", 7) == 0) { - n = ngx_atoi(&value[i].data[7], value[i].len - 7); + n = ngx_atoi(value[1].data, value[1].len); - if (n == NGX_ERROR || n == 0) { - goto invalid; - } + if (n == NGX_ERROR || n == 0) { + ngx_conf_log_error(NGX_LOG_EMERG, cf, 0, + "invalid value \"%V\" in \"%V\" directive", + &value[1], &cmd->name); + return NGX_CONF_ERROR; + } - kcf->max_cached = n; + kcf->max_cached = n; + + for (i = 2; i < cf->args->nelts; i++) { + + if (ngx_strcmp(value[i].data, "single") == 0) { + + kcf->single = 1; continue; }