# HG changeset patch # User Roman Arutyunyan # Date 1416332472 -10800 # Node ID 2f7e557eab5b501ba71418febd3de9ef1c0ab4f1 # Parent abb466a57a22b3ca07302d8d39bfc4cf37fd11bc Cache: proxy_cache_lock_age and friends. Once this age is reached, the cache lock is discarded and another request can acquire the lock. Requests which failed to acquire the lock are not allowed to cache the response. diff --git a/src/http/modules/ngx_http_fastcgi_module.c b/src/http/modules/ngx_http_fastcgi_module.c --- a/src/http/modules/ngx_http_fastcgi_module.c +++ b/src/http/modules/ngx_http_fastcgi_module.c @@ -419,6 +419,13 @@ static ngx_command_t ngx_http_fastcgi_c offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout), NULL }, + { ngx_string("fastcgi_cache_lock_age"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_age), + NULL }, + { ngx_string("fastcgi_cache_revalidate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -2374,6 +2381,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_con conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; #endif @@ -2638,6 +2646,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, prev->upstream.cache_lock_timeout, 5000); + ngx_conf_merge_msec_value(conf->upstream.cache_lock_age, + prev->upstream.cache_lock_age, 5000); + ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); diff --git a/src/http/modules/ngx_http_proxy_module.c b/src/http/modules/ngx_http_proxy_module.c --- a/src/http/modules/ngx_http_proxy_module.c +++ b/src/http/modules/ngx_http_proxy_module.c @@ -489,6 +489,13 @@ static ngx_command_t ngx_http_proxy_com offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout), NULL }, + { ngx_string("proxy_cache_lock_age"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_age), + NULL }, + { ngx_string("proxy_cache_revalidate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -2544,6 +2551,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_ conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; #endif @@ -2818,6 +2826,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, prev->upstream.cache_lock_timeout, 5000); + ngx_conf_merge_msec_value(conf->upstream.cache_lock_age, + prev->upstream.cache_lock_age, 5000); + ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); diff --git a/src/http/modules/ngx_http_scgi_module.c b/src/http/modules/ngx_http_scgi_module.c --- a/src/http/modules/ngx_http_scgi_module.c +++ b/src/http/modules/ngx_http_scgi_module.c @@ -276,6 +276,13 @@ static ngx_command_t ngx_http_scgi_comma offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout), NULL }, + { ngx_string("scgi_cache_lock_age"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_age), + NULL }, + { ngx_string("scgi_cache_revalidate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -1133,6 +1140,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; #endif @@ -1392,6 +1400,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, prev->upstream.cache_lock_timeout, 5000); + ngx_conf_merge_msec_value(conf->upstream.cache_lock_age, + prev->upstream.cache_lock_age, 5000); + ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); diff --git a/src/http/modules/ngx_http_uwsgi_module.c b/src/http/modules/ngx_http_uwsgi_module.c --- a/src/http/modules/ngx_http_uwsgi_module.c +++ b/src/http/modules/ngx_http_uwsgi_module.c @@ -336,6 +336,13 @@ static ngx_command_t ngx_http_uwsgi_comm offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout), NULL }, + { ngx_string("uwsgi_cache_lock_age"), + NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_TAKE1, + ngx_conf_set_msec_slot, + NGX_HTTP_LOC_CONF_OFFSET, + offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_age), + NULL }, + { ngx_string("uwsgi_cache_revalidate"), NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, ngx_conf_set_flag_slot, @@ -1339,6 +1346,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_ conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; + conf->upstream.cache_lock_age = NGX_CONF_UNSET_MSEC; conf->upstream.cache_revalidate = NGX_CONF_UNSET; #endif @@ -1606,6 +1614,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, prev->upstream.cache_lock_timeout, 5000); + ngx_conf_merge_msec_value(conf->upstream.cache_lock_age, + prev->upstream.cache_lock_age, 5000); + ngx_conf_merge_value(conf->upstream.cache_revalidate, prev->upstream.cache_revalidate, 0); diff --git a/src/http/ngx_http_cache.h b/src/http/ngx_http_cache.h --- a/src/http/ngx_http_cache.h +++ b/src/http/ngx_http_cache.h @@ -57,6 +57,7 @@ typedef struct { time_t valid_sec; size_t body_start; off_t fs_size; + ngx_msec_t lock_time; } ngx_http_file_cache_node_t; @@ -91,6 +92,8 @@ struct ngx_http_cache_s { ngx_http_file_cache_node_t *node; ngx_msec_t lock_timeout; + ngx_msec_t lock_age; + ngx_msec_t lock_time; ngx_msec_t wait_time; ngx_event_t wait_event; diff --git a/src/http/ngx_http_file_cache.c b/src/http/ngx_http_file_cache.c --- a/src/http/ngx_http_file_cache.c +++ b/src/http/ngx_http_file_cache.c @@ -396,13 +396,19 @@ ngx_http_file_cache_lock(ngx_http_reques return NGX_DECLINED; } + now = ngx_current_msec; + cache = c->file_cache; ngx_shmtx_lock(&cache->shpool->mutex); - if (!c->node->updating) { + timer = c->node->lock_time - now; + + if (!c->node->updating || (ngx_msec_int_t) timer <= 0) { c->node->updating = 1; + c->node->lock_time = now + c->lock_age; c->updating = 1; + c->lock_time = c->node->lock_time; } ngx_shmtx_unlock(&cache->shpool->mutex); @@ -415,10 +421,12 @@ ngx_http_file_cache_lock(ngx_http_reques return NGX_DECLINED; } + if (c->lock_timeout == 0) { + return NGX_HTTP_CACHE_SCARCE; + } + c->waiting = 1; - now = ngx_current_msec; - if (c->wait_time == 0) { c->wait_time = now + c->lock_timeout; @@ -441,7 +449,7 @@ static void ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev) { ngx_uint_t wait; - ngx_msec_t timer; + ngx_msec_t now, timer; ngx_http_cache_t *c; ngx_http_request_t *r; ngx_http_file_cache_t *cache; @@ -449,15 +457,17 @@ ngx_http_file_cache_lock_wait_handler(ng r = ev->data; c = r->cache; + now = ngx_current_msec; + ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0, "http file cache wait handler wt:%M cur:%M", - c->wait_time, ngx_current_msec); - - timer = c->wait_time - ngx_current_msec; + c->wait_time, now); + + timer = c->wait_time - now; if ((ngx_msec_int_t) timer <= 0) { ngx_log_error(NGX_LOG_INFO, ev->log, 0, "cache lock timeout"); - c->lock = 0; + c->lock_timeout = 0; goto wakeup; } @@ -466,7 +476,9 @@ ngx_http_file_cache_lock_wait_handler(ng ngx_shmtx_lock(&cache->shpool->mutex); - if (c->node->updating) { + timer = c->node->lock_time - now; + + if (c->node->updating && (ngx_msec_int_t) timer > 0) { wait = 1; } @@ -588,6 +600,7 @@ ngx_http_file_cache_read(ngx_http_reques } else { c->node->updating = 1; c->updating = 1; + c->lock_time = c->node->lock_time; rc = NGX_HTTP_CACHE_STALE; } @@ -1453,7 +1466,7 @@ ngx_http_file_cache_free(ngx_http_cache_ fcn = c->node; fcn->count--; - if (c->updating) { + if (c->updating && fcn->lock_time == c->lock_time) { fcn->updating = 0; } diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c --- a/src/http/ngx_http_upstream.c +++ b/src/http/ngx_http_upstream.c @@ -784,6 +784,7 @@ ngx_http_upstream_cache(ngx_http_request c->lock = u->conf->cache_lock; c->lock_timeout = u->conf->cache_lock_timeout; + c->lock_age = u->conf->cache_lock_age; u->cache_status = NGX_HTTP_CACHE_MISS; } diff --git a/src/http/ngx_http_upstream.h b/src/http/ngx_http_upstream.h --- a/src/http/ngx_http_upstream.h +++ b/src/http/ngx_http_upstream.h @@ -183,6 +183,7 @@ typedef struct { ngx_flag_t cache_lock; ngx_msec_t cache_lock_timeout; + ngx_msec_t cache_lock_age; ngx_flag_t cache_revalidate;