#! /bin/sh /usr/share/dpatch/dpatch-run ## ngx_http_upstream_count_limit-0.1.dpatch by Kirill A. Korinskiy ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: Implement upstream_count_limit @DPATCH@ diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c index 6ed7c8f..c1cd8ed 100644 --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -9,6 +9,11 @@ #include +typedef struct { + ngx_uint_t count_limit; +} ngx_http_upstream_local_conf_t; + + static void ngx_http_upstream_resolve_handler(ngx_resolver_ctx_t *ctx); static void ngx_http_upstream_rd_check_broken_connection(ngx_http_request_t *r); static void ngx_http_upstream_wr_check_broken_connection(ngx_http_request_t *r); @@ -106,6 +111,10 @@ static char *ngx_http_upstream_server(ngx_conf_t *cf, ngx_command_t *cmd, static void *ngx_http_upstream_create_main_conf(ngx_conf_t *cf); static char *ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf); +static void *ngx_http_upstream_create_local_conf(ngx_conf_t *cf); +static char *ngx_http_upstream_merge_local_conf(ngx_conf_t *cf, + void *parent, void *child); + #if (NGX_HTTP_SSL) static void ngx_http_upstream_ssl_init_connection(ngx_http_request_t *, ngx_http_upstream_t *u, ngx_connection_t *c); @@ -249,6 +258,14 @@ static ngx_command_t ngx_http_upstream_commands[] = { 0, NULL }, + { ngx_string("upstream_count_limit"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_HTTP_LIF_CONF + |NGX_CONF_FLAG, + ngx_conf_set_num_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_upstream_local_conf_t, count_limit), + NULL }, + ngx_null_command }; @@ -263,8 +280,8 @@ static ngx_http_module_t ngx_http_upstream_module_ctx = { NULL, /* create server configuration */ NULL, /* merge server configuration */ - NULL, /* create location configuration */ - NULL /* merge location configuration */ + ngx_http_upstream_create_local_conf, /* create location configuration */ + ngx_http_upstream_merge_local_conf /* merge location configuration */ }; @@ -327,6 +344,9 @@ ngx_http_upstream_init(ngx_http_request_t *r) ngx_http_core_loc_conf_t *clcf; ngx_http_upstream_srv_conf_t *uscf, **uscfp; ngx_http_upstream_main_conf_t *umcf; + ngx_http_upstream_local_conf_t *conf; + + conf = ngx_http_get_module_loc_conf(r, ngx_http_upstream_module); c = r->connection; @@ -344,6 +364,11 @@ ngx_http_upstream_init(ngx_http_request_t *r) r->write_event_handler = ngx_http_upstream_wr_check_broken_connection; } + if (conf->count_limit) { + u->count_limit = conf->count_limit; + u->count_limit_origin = conf->count_limit; + } + if (ngx_event_flags & NGX_USE_CLEAR_EVENT) { if (!c->write->active) { @@ -760,6 +785,10 @@ ngx_http_upstream_connect(ngx_http_request_t *r, ngx_http_upstream_t *u) u->state->peer = u->peer.name; + if (u->count_limit_origin) { + u->count_limit--; + } + if (rc == NGX_BUSY) { ngx_log_error(NGX_LOG_ERR, r->connection->log, 0, "no live upstreams"); ngx_http_upstream_next(r, u, NGX_HTTP_UPSTREAM_FT_NOLIVE); @@ -2375,6 +2404,14 @@ ngx_http_upstream_next(ngx_http_request_t *r, ngx_http_upstream_t *u, { ngx_uint_t status, state; + if (u->count_limit_origin && u->count_limit == 0) { + ngx_log_error(NGX_LOG_INFO, r->connection->log, 0, + "http next upstream limited by upstream_count_limit %d ", + u->count_limit_origin); + ngx_http_upstream_finalize_request(r, u, NGX_HTTP_BAD_GATEWAY); + return; + } + ngx_log_debug1(NGX_LOG_DEBUG_HTTP, r->connection->log, 0, "http next upstream, %xi", ft_type); @@ -3782,3 +3819,31 @@ ngx_http_upstream_init_main_conf(ngx_conf_t *cf, void *conf) return NGX_CONF_OK; } + + +static void * +ngx_http_upstream_create_local_conf(ngx_conf_t *cf) +{ + ngx_http_upstream_local_conf_t *conf; + + conf = ngx_pcalloc(cf->pool, sizeof(ngx_http_upstream_local_conf_t)); + if (conf == NULL) { + return NGX_CONF_ERROR; + } + + conf->count_limit = NGX_CONF_UNSET_UINT; + + return conf; +} + +static char * +ngx_http_upstream_merge_local_conf(ngx_conf_t *cf, void *parent, void *child) +{ + ngx_http_upstream_local_conf_t *prev = parent; + ngx_http_upstream_local_conf_t *conf = child; + + ngx_conf_merge_uint_value(conf->count_limit, + prev->count_limit, 0); + + return NGX_CONF_OK; +} diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h index 3c14127..c2faead 100644 --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -273,6 +273,9 @@ struct ngx_http_upstream_s { ngx_http_cleanup_pt *cleanup; + ngx_flag_t count_limit; + ngx_uint_t count_limit_origin; + unsigned store:1; unsigned cacheable:1; unsigned accel:1;