Skip to content

Instantly share code, notes, and snippets.

@gregvish
Created September 15, 2013 16:01
Show Gist options
  • Save gregvish/6572002 to your computer and use it in GitHub Desktop.
Save gregvish/6572002 to your computer and use it in GitHub Desktop.
diff --git a/auto/modules b/auto/modules
index a78e785..30e1645 100644
--- a/auto/modules
+++ b/auto/modules
@@ -376,6 +376,7 @@ if [ $HTTP_UPSTREAM_LEAST_CONN = YES ]; then
fi
if [ $HTTP_UPSTREAM_KEEPALIVE = YES ]; then
+ have=NGX_HTTP_UPSTREAM_KEEPALIVE . auto/have
HTTP_MODULES="$HTTP_MODULES $HTTP_UPSTREAM_KEEPALIVE_MODULE"
HTTP_SRCS="$HTTP_SRCS $HTTP_UPSTREAM_KEEPALIVE_SRCS"
fi
diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c
index 5e62caa..9fee00b 100644
--- a/src/http/modules/ngx_http_proxy_module.c
+++ b/src/http/modules/ngx_http_proxy_module.c
@@ -513,6 +513,22 @@ static ngx_command_t ngx_http_proxy_commands[] = {
#endif
+#if (NGX_HTTP_UPSTREAM_KEEPALIVE)
+ { ngx_string("proxy_upstream_default_keepalive"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
+ ngx_conf_set_flag_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.default_keepalive),
+ NULL },
+
+ { ngx_string("proxy_upstream_default_keepalive_max_connections"),
+ NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1,
+ ngx_conf_set_size_slot,
+ NGX_HTTP_LOC_CONF_OFFSET,
+ offsetof(ngx_http_proxy_loc_conf_t, upstream.default_keepalive_max_connections),
+ NULL },
+#endif
+
ngx_null_command
};
@@ -2385,6 +2401,11 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
* conf->redirects = NULL;
*/
+#if (NGX_HTTP_UPSTREAM_KEEPALIVE)
+ conf->upstream.default_keepalive = NGX_CONF_UNSET;
+ conf->upstream.default_keepalive_max_connections = NGX_CONF_UNSET_SIZE;
+#endif
+
conf->upstream.store = NGX_CONF_UNSET;
conf->upstream.store_access = NGX_CONF_UNSET_UINT;
conf->upstream.buffering = NGX_CONF_UNSET;
@@ -2467,6 +2488,20 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
}
}
+#if (NGX_HTTP_UPSTREAM_KEEPALIVE)
+ ngx_conf_merge_uint_value(conf->upstream.default_keepalive,
+ prev->upstream.default_keepalive, 0);
+
+ ngx_conf_merge_size_value(conf->upstream.default_keepalive_max_connections,
+ prev->upstream.default_keepalive_max_connections, 10);
+
+ if (conf->upstream.default_keepalive) {
+ if (ngx_http_upstream_default_keepalive_init(cf, &(conf->upstream)) != NGX_CONF_OK) {
+ return NGX_CONF_ERROR;
+ }
+ }
+#endif
+
ngx_conf_merge_uint_value(conf->upstream.store_access,
prev->upstream.store_access, 0600);
diff --git a/src/http/modules/ngx_http_upstream_keepalive_module.c b/src/http/modules/ngx_http_upstream_keepalive_module.c
index eed1174..3723668 100644
--- a/src/http/modules/ngx_http_upstream_keepalive_module.c
+++ b/src/http/modules/ngx_http_upstream_keepalive_module.c
@@ -36,6 +36,8 @@ typedef struct {
ngx_event_set_peer_session_pt original_set_session;
ngx_event_save_peer_session_pt original_save_session;
#endif
+
+ ngx_str_t host;
} ngx_http_upstream_keepalive_peer_data_t;
@@ -49,6 +51,9 @@ typedef struct {
socklen_t socklen;
u_char sockaddr[NGX_SOCKADDRLEN];
+ char host[NGX_MAXHOSTNAMELEN];
+ uint16_t host_len;
+
} ngx_http_upstream_keepalive_cache_t;
@@ -184,6 +189,8 @@ ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
return NGX_ERROR;
}
+ kp->host = us->host;
+
kp->conf = kcf;
kp->upstream = r->upstream;
kp->data = r->upstream->peer.data;
@@ -238,8 +245,9 @@ ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
c = item->connection;
if (ngx_memn2cmp((u_char *) &item->sockaddr, (u_char *) pc->sockaddr,
- item->socklen, pc->socklen)
- == 0)
+ item->socklen, pc->socklen) == 0 &&
+ ngx_memn2cmp((u_char *) &item->host, (u_char *) kp->host.data,
+ item->host_len, kp->host.len) == 0)
{
ngx_queue_remove(q);
ngx_queue_insert_head(&kp->conf->free, q);
@@ -345,6 +353,8 @@ ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
item->socklen = pc->socklen;
ngx_memcpy(&item->sockaddr, pc->sockaddr, pc->socklen);
+ item->host_len = kp->host.len;
+ ngx_memcpy(&item->host, kp->host.data, ngx_min(kp->host.len, NGX_MAXHOSTNAMELEN));
if (c->read->ready) {
ngx_http_upstream_keepalive_close_handler(c->read);
@@ -537,3 +547,77 @@ invalid:
return NGX_CONF_ERROR;
}
+
+char *
+ngx_http_upstream_default_keepalive_init(ngx_conf_t *cf,
+ ngx_http_upstream_conf_t *umcf)
+{
+ ngx_uint_t i;
+ ngx_http_upstream_keepalive_cache_t *cached;
+ ngx_http_upstream_keepalive_srv_conf_t *kcf;
+
+ kcf = ngx_pcalloc(cf->pool,
+ sizeof(ngx_http_upstream_keepalive_srv_conf_t));
+ if (kcf == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ kcf->max_cached = umcf->default_keepalive_max_connections;
+
+ cached = ngx_pcalloc(cf->pool,
+ sizeof(ngx_http_upstream_keepalive_cache_t) * kcf->max_cached);
+ if (cached == NULL) {
+ return NGX_CONF_ERROR;
+ }
+
+ ngx_queue_init(&kcf->cache);
+ ngx_queue_init(&kcf->free);
+
+ for (i = 0; i < kcf->max_cached; i += 1) {
+ ngx_queue_insert_head(&kcf->free, &cached[i].queue);
+ cached[i].conf = kcf;
+ }
+
+ umcf->default_keepalive_cache = kcf;
+
+ return NGX_CONF_OK;
+}
+
+ngx_int_t
+ngx_http_upstream_default_keepalive_adapt_peer(ngx_http_request_t *r,
+ ngx_http_upstream_resolved_t *ur)
+{
+ ngx_http_upstream_keepalive_peer_data_t *kp;
+ ngx_http_upstream_keepalive_srv_conf_t *kcf;
+
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "default keepalive adapt peer");
+
+ kcf = r->upstream->conf->default_keepalive_cache;
+
+ kp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_keepalive_peer_data_t));
+ if (kp == NULL) {
+ return NGX_ERROR;
+ }
+
+ kp->host = ur->host;
+
+ kp->conf = kcf;
+ kp->upstream = r->upstream;
+ kp->data = r->upstream->peer.data;
+ kp->original_get_peer = r->upstream->peer.get;
+ kp->original_free_peer = r->upstream->peer.free;
+
+ r->upstream->peer.data = kp;
+ r->upstream->peer.get = ngx_http_upstream_get_keepalive_peer;
+ r->upstream->peer.free = ngx_http_upstream_free_keepalive_peer;
+
+#if (NGX_HTTP_SSL)
+ kp->original_set_session = r->upstream->peer.set_session;
+ kp->original_save_session = r->upstream->peer.save_session;
+ r->upstream->peer.set_session = ngx_http_upstream_keepalive_set_session;
+ r->upstream->peer.save_session = ngx_http_upstream_keepalive_save_session;
+#endif
+
+ return NGX_OK;
+}
diff --git a/src/http/ngx_http.h b/src/http/ngx_http.h
index d4dc1bd..4d54634 100644
--- a/src/http/ngx_http.h
+++ b/src/http/ngx_http.h
@@ -51,6 +51,10 @@ typedef u_char *(*ngx_http_log_handler_pt)(ngx_http_request_t *r,
#if (NGX_HTTP_SSL)
#include <ngx_http_ssl_module.h>
#endif
+#if (NGX_HTTP_UPSTREAM_KEEPALIVE)
+#include <ngx_http_upstream_keepalive_module.h>
+#endif
+
struct ngx_http_log_ctx_s {
diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
index 45e2eb7..2a2ca1c 100644
--- a/src/http/ngx_http_upstream.c
+++ b/src/http/ngx_http_upstream.c
@@ -931,6 +931,15 @@ ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx)
goto failed;
}
+#if (NGX_HTTP_UPSTREAM_KEEPALIVE)
+ if (r->upstream->conf->default_keepalive) {
+ if (ngx_http_upstream_default_keepalive_adapt_peer(r, ur) != NGX_OK) {
+ ngx_log_debug0(NGX_LOG_DEBUG_HTTP, r->connection->log, 0,
+ "http upstream default keepalive: can't keepalive peer");
+ }
+ }
+#endif
+
ngx_resolve_name_done(ctx);
ur->ctx = NULL;
diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h
index 29ebf9b..7564050 100644
--- a/src/http/ngx_http_upstream.h
+++ b/src/http/ngx_http_upstream.h
@@ -194,6 +194,12 @@ typedef struct {
#endif
ngx_str_t module;
+
+#if (NGX_HTTP_UPSTREAM_KEEPALIVE)
+ ngx_uint_t default_keepalive;
+ ngx_uint_t default_keepalive_max_connections;
+ void *default_keepalive_cache;
+#endif
} ngx_http_upstream_conf_t;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment