changeset 5905:2f7e557eab5b

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.
author Roman Arutyunyan <arut@nginx.com>
date Tue, 18 Nov 2014 20:41:12 +0300
parents abb466a57a22
children 548f704c1907
files src/http/modules/ngx_http_fastcgi_module.c src/http/modules/ngx_http_proxy_module.c src/http/modules/ngx_http_scgi_module.c src/http/modules/ngx_http_uwsgi_module.c src/http/ngx_http_cache.h src/http/ngx_http_file_cache.c src/http/ngx_http_upstream.c src/http/ngx_http_upstream.h
diffstat 8 files changed, 72 insertions(+), 10 deletions(-) [+]
line wrap: on
line diff
--- a/src/http/modules/ngx_http_fastcgi_module.c	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/modules/ngx_http_fastcgi_module.c	Tue Nov 18 20:41:12 2014 +0300
@@ -419,6 +419,13 @@
       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 @@
     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_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);
 
--- a/src/http/modules/ngx_http_proxy_module.c	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/modules/ngx_http_proxy_module.c	Tue Nov 18 20:41:12 2014 +0300
@@ -489,6 +489,13 @@
       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 @@
     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_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);
 
--- a/src/http/modules/ngx_http_scgi_module.c	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/modules/ngx_http_scgi_module.c	Tue Nov 18 20:41:12 2014 +0300
@@ -276,6 +276,13 @@
       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 @@
     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_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);
 
--- a/src/http/modules/ngx_http_uwsgi_module.c	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/modules/ngx_http_uwsgi_module.c	Tue Nov 18 20:41:12 2014 +0300
@@ -336,6 +336,13 @@
       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 @@
     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_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);
 
--- a/src/http/ngx_http_cache.h	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/ngx_http_cache.h	Tue Nov 18 20:41:12 2014 +0300
@@ -57,6 +57,7 @@
     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 @@
     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;
--- a/src/http/ngx_http_file_cache.c	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/ngx_http_file_cache.c	Tue Nov 18 20:41:12 2014 +0300
@@ -396,13 +396,19 @@
         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 @@
         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 @@
 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 @@
     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_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 @@
         } else {
             c->node->updating = 1;
             c->updating = 1;
+            c->lock_time = c->node->lock_time;
             rc = NGX_HTTP_CACHE_STALE;
         }
 
@@ -1453,7 +1466,7 @@
     fcn = c->node;
     fcn->count--;
 
-    if (c->updating) {
+    if (c->updating && fcn->lock_time == c->lock_time) {
         fcn->updating = 0;
     }
 
--- a/src/http/ngx_http_upstream.c	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/ngx_http_upstream.c	Tue Nov 18 20:41:12 2014 +0300
@@ -784,6 +784,7 @@
 
         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;
     }
--- a/src/http/ngx_http_upstream.h	Fri Nov 07 17:22:19 2014 +0300
+++ b/src/http/ngx_http_upstream.h	Tue Nov 18 20:41:12 2014 +0300
@@ -183,6 +183,7 @@
 
     ngx_flag_t                       cache_lock;
     ngx_msec_t                       cache_lock_timeout;
+    ngx_msec_t                       cache_lock_age;
 
     ngx_flag_t                       cache_revalidate;