changeset 0:725ee11164f3

Keepalive upstream balancer: transparent skeleton.
author Maxim Dounin <mdounin@mdounin.ru>
date Mon, 20 Oct 2008 18:00:33 +0400
parents
children ca955a7f651b
files config ngx_http_upstream_keepalive_module.c
diffstat 2 files changed, 216 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/config	Mon Oct 20 18:00:33 2008 +0400
@@ -0,0 +1,7 @@
+ngx_addon_name="ngx_http_upstream_keepalive_module"
+
+HTTP_MODULES="$HTTP_MODULES \
+	ngx_http_upstream_keepalive_module"
+
+NGX_ADDON_SRCS="$NGX_ADDON_SRCS \
+	$ngx_addon_dir/ngx_http_upstream_keepalive_module.c"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ngx_http_upstream_keepalive_module.c	Mon Oct 20 18:00:33 2008 +0400
@@ -0,0 +1,209 @@
+
+/*
+ * Copyright (C) Igor Sysoev
+ */
+
+
+#include <ngx_config.h>
+#include <ngx_core.h>
+#include <ngx_http.h>
+
+
+typedef struct {
+    ngx_int_t                          cached;
+
+    ngx_http_upstream_init_pt          original_init_upstream;
+    ngx_http_upstream_init_peer_pt     original_init_peer;
+
+} ngx_http_upstream_keepalive_srv_conf_t;
+
+typedef struct {
+    void                              *data;
+
+    ngx_event_get_peer_pt              original_get_peer;
+    ngx_event_free_peer_pt             original_free_peer;
+
+} ngx_http_upstream_keepalive_peer_data_t;
+
+
+static ngx_int_t ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
+    ngx_http_upstream_srv_conf_t *us);
+static ngx_int_t ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc,
+    void *data);
+static void ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc,
+    void *data, ngx_uint_t state);
+
+static void *ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf);
+static char *ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd,
+    void *conf);
+
+
+static ngx_command_t  ngx_http_upstream_keepalive_commands[] = {
+
+    { ngx_string("keepalive"),
+      NGX_HTTP_UPS_CONF|NGX_CONF_NOARGS,
+      ngx_http_upstream_keepalive,
+      0,
+      0,
+      NULL },
+
+      ngx_null_command
+};
+
+
+static ngx_http_module_t  ngx_http_upstream_keepalive_module_ctx = {
+    NULL,                                  /* preconfiguration */
+    NULL,                                  /* postconfiguration */
+
+    NULL,                                  /* create main configuration */
+    NULL,                                  /* init main configuration */
+
+    ngx_http_upstream_keepalive_create_conf, /* create server configuration */
+    NULL,                                  /* merge server configuration */
+
+    NULL,                                  /* create location configuration */
+    NULL                                   /* merge location configuration */
+};
+
+
+ngx_module_t  ngx_http_upstream_keepalive_module = {
+    NGX_MODULE_V1,
+    &ngx_http_upstream_keepalive_module_ctx, /* module context */
+    ngx_http_upstream_keepalive_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_keepalive(ngx_conf_t *cf,
+    ngx_http_upstream_srv_conf_t *us)
+{
+    ngx_http_upstream_keepalive_srv_conf_t  *kcf;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, cf->log, 0,
+                   "init keepalive");
+
+    kcf = ngx_http_conf_upstream_srv_conf(us,
+                                          ngx_http_upstream_keepalive_module);
+
+    if (kcf->original_init_upstream(cf, us) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    kcf->original_init_peer = us->peer.init;
+
+    us->peer.init = ngx_http_upstream_init_keepalive_peer;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_init_keepalive_peer(ngx_http_request_t *r,
+    ngx_http_upstream_srv_conf_t *us)
+{
+    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,
+                   "init keepalive peer");
+
+    kcf = ngx_http_conf_upstream_srv_conf(us,
+                                          ngx_http_upstream_keepalive_module);
+
+    kp = ngx_palloc(r->pool, sizeof(ngx_http_upstream_keepalive_peer_data_t));
+    if (kp == NULL) {
+        return NGX_ERROR;
+    }
+
+    if (kcf->original_init_peer(r, us) != NGX_OK) {
+        return NGX_ERROR;
+    }
+
+    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;
+
+    return NGX_OK;
+}
+
+
+static ngx_int_t
+ngx_http_upstream_get_keepalive_peer(ngx_peer_connection_t *pc, void *data)
+{
+    ngx_http_upstream_keepalive_peer_data_t  *kp = data;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+                   "get keepalive peer");
+
+    return kp->original_get_peer(pc, kp->data);
+}
+
+
+static void
+ngx_http_upstream_free_keepalive_peer(ngx_peer_connection_t *pc, void *data,
+    ngx_uint_t state)
+{
+    ngx_http_upstream_keepalive_peer_data_t  *kp = data;
+
+    ngx_log_debug0(NGX_LOG_DEBUG_HTTP, pc->log, 0,
+                   "free keepalive peer");
+
+    return kp->original_free_peer(pc, kp->data, state);
+}
+
+
+static void *
+ngx_http_upstream_keepalive_create_conf(ngx_conf_t *cf)
+{
+    ngx_http_upstream_keepalive_srv_conf_t  *conf;
+
+    conf = ngx_pcalloc(cf->pool,
+                       sizeof(ngx_http_upstream_keepalive_srv_conf_t));
+    if (conf == NULL) {
+        return NGX_CONF_ERROR;
+    }
+
+    /*
+     * set by ngx_pcalloc():
+     *
+     *     conf->cached = 0;
+     *     conf->original_init_upstream = NULL;
+     *     conf->original_init_peer = NULL;
+     */
+
+    return conf;
+}
+
+
+static char *
+ngx_http_upstream_keepalive(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
+{
+    ngx_http_upstream_srv_conf_t            *uscf;
+    ngx_http_upstream_keepalive_srv_conf_t  *kcf;
+
+    uscf = ngx_http_conf_get_module_srv_conf(cf, ngx_http_upstream_module);
+
+    kcf = ngx_http_conf_upstream_srv_conf(uscf,
+                                          ngx_http_upstream_keepalive_module);
+
+    kcf->original_init_upstream = uscf->peer.init_upstream
+                                  ? uscf->peer.init_upstream
+                                  : ngx_http_upstream_init_round_robin;
+
+    uscf->peer.init_upstream = ngx_http_upstream_init_keepalive;
+
+    return NGX_CONF_OK;
+}