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.
This commit is contained in:
Roman Arutyunyan 2014-11-18 20:41:12 +03:00
parent 20d41493d4
commit 2628cc11d4
8 changed files with 71 additions and 9 deletions

View File

@ -419,6 +419,13 @@ static ngx_command_t ngx_http_fastcgi_commands[] = {
offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout), offsetof(ngx_http_fastcgi_loc_conf_t, upstream.cache_lock_timeout),
NULL }, 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_string("fastcgi_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot, ngx_conf_set_flag_slot,
@ -2374,6 +2381,7 @@ ngx_http_fastcgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; 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; conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif #endif
@ -2638,6 +2646,9 @@ ngx_http_fastcgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000); 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, ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0); prev->upstream.cache_revalidate, 0);

View File

@ -489,6 +489,13 @@ static ngx_command_t ngx_http_proxy_commands[] = {
offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout), offsetof(ngx_http_proxy_loc_conf_t, upstream.cache_lock_timeout),
NULL }, 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_string("proxy_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot, ngx_conf_set_flag_slot,
@ -2544,6 +2551,7 @@ ngx_http_proxy_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; 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; conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif #endif
@ -2818,6 +2826,9 @@ ngx_http_proxy_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000); 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, ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0); prev->upstream.cache_revalidate, 0);

View File

@ -276,6 +276,13 @@ static ngx_command_t ngx_http_scgi_commands[] = {
offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout), offsetof(ngx_http_scgi_loc_conf_t, upstream.cache_lock_timeout),
NULL }, 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_string("scgi_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot, ngx_conf_set_flag_slot,
@ -1133,6 +1140,7 @@ ngx_http_scgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; 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; conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif #endif
@ -1392,6 +1400,9 @@ ngx_http_scgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000); 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, ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0); prev->upstream.cache_revalidate, 0);

View File

@ -336,6 +336,13 @@ static ngx_command_t ngx_http_uwsgi_commands[] = {
offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout), offsetof(ngx_http_uwsgi_loc_conf_t, upstream.cache_lock_timeout),
NULL }, 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_string("uwsgi_cache_revalidate"),
NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG, NGX_HTTP_MAIN_CONF|NGX_HTTP_SRV_CONF|NGX_HTTP_LOC_CONF|NGX_CONF_FLAG,
ngx_conf_set_flag_slot, ngx_conf_set_flag_slot,
@ -1339,6 +1346,7 @@ ngx_http_uwsgi_create_loc_conf(ngx_conf_t *cf)
conf->upstream.cache_valid = NGX_CONF_UNSET_PTR; conf->upstream.cache_valid = NGX_CONF_UNSET_PTR;
conf->upstream.cache_lock = NGX_CONF_UNSET; conf->upstream.cache_lock = NGX_CONF_UNSET;
conf->upstream.cache_lock_timeout = NGX_CONF_UNSET_MSEC; 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; conf->upstream.cache_revalidate = NGX_CONF_UNSET;
#endif #endif
@ -1606,6 +1614,9 @@ ngx_http_uwsgi_merge_loc_conf(ngx_conf_t *cf, void *parent, void *child)
ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout, ngx_conf_merge_msec_value(conf->upstream.cache_lock_timeout,
prev->upstream.cache_lock_timeout, 5000); 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, ngx_conf_merge_value(conf->upstream.cache_revalidate,
prev->upstream.cache_revalidate, 0); prev->upstream.cache_revalidate, 0);

View File

@ -57,6 +57,7 @@ typedef struct {
time_t valid_sec; time_t valid_sec;
size_t body_start; size_t body_start;
off_t fs_size; off_t fs_size;
ngx_msec_t lock_time;
} ngx_http_file_cache_node_t; } ngx_http_file_cache_node_t;
@ -91,6 +92,8 @@ struct ngx_http_cache_s {
ngx_http_file_cache_node_t *node; ngx_http_file_cache_node_t *node;
ngx_msec_t lock_timeout; ngx_msec_t lock_timeout;
ngx_msec_t lock_age;
ngx_msec_t lock_time;
ngx_msec_t wait_time; ngx_msec_t wait_time;
ngx_event_t wait_event; ngx_event_t wait_event;

View File

@ -396,13 +396,19 @@ ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
return NGX_DECLINED; return NGX_DECLINED;
} }
now = ngx_current_msec;
cache = c->file_cache; cache = c->file_cache;
ngx_shmtx_lock(&cache->shpool->mutex); 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->updating = 1;
c->node->lock_time = now + c->lock_age;
c->updating = 1; c->updating = 1;
c->lock_time = c->node->lock_time;
} }
ngx_shmtx_unlock(&cache->shpool->mutex); ngx_shmtx_unlock(&cache->shpool->mutex);
@ -415,9 +421,11 @@ ngx_http_file_cache_lock(ngx_http_request_t *r, ngx_http_cache_t *c)
return NGX_DECLINED; return NGX_DECLINED;
} }
c->waiting = 1; if (c->lock_timeout == 0) {
return NGX_HTTP_CACHE_SCARCE;
}
now = ngx_current_msec; c->waiting = 1;
if (c->wait_time == 0) { if (c->wait_time == 0) {
c->wait_time = now + c->lock_timeout; 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_http_file_cache_lock_wait_handler(ngx_event_t *ev)
{ {
ngx_uint_t wait; ngx_uint_t wait;
ngx_msec_t timer; ngx_msec_t now, timer;
ngx_http_cache_t *c; ngx_http_cache_t *c;
ngx_http_request_t *r; ngx_http_request_t *r;
ngx_http_file_cache_t *cache; ngx_http_file_cache_t *cache;
@ -449,15 +457,17 @@ ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev)
r = ev->data; r = ev->data;
c = r->cache; c = r->cache;
now = ngx_current_msec;
ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0, ngx_log_debug2(NGX_LOG_DEBUG_HTTP, ev->log, 0,
"http file cache wait handler wt:%M cur:%M", "http file cache wait handler wt:%M cur:%M",
c->wait_time, ngx_current_msec); c->wait_time, now);
timer = c->wait_time - ngx_current_msec; timer = c->wait_time - now;
if ((ngx_msec_int_t) timer <= 0) { if ((ngx_msec_int_t) timer <= 0) {
ngx_log_error(NGX_LOG_INFO, ev->log, 0, "cache lock timeout"); ngx_log_error(NGX_LOG_INFO, ev->log, 0, "cache lock timeout");
c->lock = 0; c->lock_timeout = 0;
goto wakeup; goto wakeup;
} }
@ -466,7 +476,9 @@ ngx_http_file_cache_lock_wait_handler(ngx_event_t *ev)
ngx_shmtx_lock(&cache->shpool->mutex); 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; wait = 1;
} }
@ -588,6 +600,7 @@ ngx_http_file_cache_read(ngx_http_request_t *r, ngx_http_cache_t *c)
} else { } else {
c->node->updating = 1; c->node->updating = 1;
c->updating = 1; c->updating = 1;
c->lock_time = c->node->lock_time;
rc = NGX_HTTP_CACHE_STALE; rc = NGX_HTTP_CACHE_STALE;
} }
@ -1453,7 +1466,7 @@ ngx_http_file_cache_free(ngx_http_cache_t *c, ngx_temp_file_t *tf)
fcn = c->node; fcn = c->node;
fcn->count--; fcn->count--;
if (c->updating) { if (c->updating && fcn->lock_time == c->lock_time) {
fcn->updating = 0; fcn->updating = 0;
} }

View File

@ -784,6 +784,7 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
c->lock = u->conf->cache_lock; c->lock = u->conf->cache_lock;
c->lock_timeout = u->conf->cache_lock_timeout; c->lock_timeout = u->conf->cache_lock_timeout;
c->lock_age = u->conf->cache_lock_age;
u->cache_status = NGX_HTTP_CACHE_MISS; u->cache_status = NGX_HTTP_CACHE_MISS;
} }

View File

@ -183,6 +183,7 @@ typedef struct {
ngx_flag_t cache_lock; ngx_flag_t cache_lock;
ngx_msec_t cache_lock_timeout; ngx_msec_t cache_lock_timeout;
ngx_msec_t cache_lock_age;
ngx_flag_t cache_revalidate; ngx_flag_t cache_revalidate;