[nginx] Background subrequests for cache updates.

Roman Arutyunyan arut at nginx.com
Thu May 25 15:18:52 UTC 2017


details:   http://hg.nginx.org/nginx/rev/9552758a786e
branches:  
changeset: 7006:9552758a786e
user:      Roman Arutyunyan <arut at nginx.com>
date:      Thu May 25 15:57:59 2017 +0300
description:
Background subrequests for cache updates.

Previously, cache background update might not work as expected, making client
wait for it to complete before receiving the final part of a stale response.
This could happen if the response could not be sent to the client socket in one
filter chain call.

Now background cache update is done in a background subrequest.  This type of
subrequest does not block any other subrequests or the main request.

diffstat:

 src/http/ngx_http_core_module.c |  41 ++++++++++++++++++++++-------------------
 src/http/ngx_http_request.c     |  27 ++++++++++++++++++++++++---
 src/http/ngx_http_request.h     |   3 ++-
 src/http/ngx_http_upstream.c    |   8 ++++----
 4 files changed, 52 insertions(+), 27 deletions(-)

diffs (185 lines):

diff -r 3e2d90073adf -r 9552758a786e src/http/ngx_http_core_module.c
--- a/src/http/ngx_http_core_module.c	Wed May 24 13:17:08 2017 +0300
+++ b/src/http/ngx_http_core_module.c	Thu May 25 15:57:59 2017 +0300
@@ -2518,6 +2518,7 @@ ngx_http_subrequest(ngx_http_request_t *
 
     sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
     sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
+    sr->background = (flags & NGX_HTTP_SUBREQUEST_BACKGROUND) != 0;
 
     sr->unparsed_uri = r->unparsed_uri;
     sr->method_name = ngx_http_core_get_method;
@@ -2531,29 +2532,31 @@ ngx_http_subrequest(ngx_http_request_t *
     sr->read_event_handler = ngx_http_request_empty_handler;
     sr->write_event_handler = ngx_http_handler;
 
-    if (c->data == r && r->postponed == NULL) {
-        c->data = sr;
-    }
-
     sr->variables = r->variables;
 
     sr->log_handler = r->log_handler;
 
-    pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
-    if (pr == NULL) {
-        return NGX_ERROR;
-    }
-
-    pr->request = sr;
-    pr->out = NULL;
-    pr->next = NULL;
-
-    if (r->postponed) {
-        for (p = r->postponed; p->next; p = p->next) { /* void */ }
-        p->next = pr;
-
-    } else {
-        r->postponed = pr;
+    if (!sr->background) {
+        if (c->data == r && r->postponed == NULL) {
+            c->data = sr;
+        }
+
+        pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
+        if (pr == NULL) {
+            return NGX_ERROR;
+        }
+
+        pr->request = sr;
+        pr->out = NULL;
+        pr->next = NULL;
+
+        if (r->postponed) {
+            for (p = r->postponed; p->next; p = p->next) { /* void */ }
+            p->next = pr;
+
+        } else {
+            r->postponed = pr;
+        }
     }
 
     sr->internal = 1;
diff -r 3e2d90073adf -r 9552758a786e src/http/ngx_http_request.c
--- a/src/http/ngx_http_request.c	Wed May 24 13:17:08 2017 +0300
+++ b/src/http/ngx_http_request.c	Thu May 25 15:57:59 2017 +0300
@@ -2357,6 +2357,26 @@ ngx_http_finalize_request(ngx_http_reque
     }
 
     if (r != r->main) {
+        clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
+
+        if (r->background) {
+            if (!r->logged) {
+                if (clcf->log_subrequest) {
+                    ngx_http_log_request(r);
+                }
+
+                r->logged = 1;
+
+            } else {
+                ngx_log_error(NGX_LOG_ALERT, c->log, 0,
+                              "subrequest: \"%V?%V\" logged again",
+                              &r->uri, &r->args);
+            }
+
+            r->done = 1;
+            ngx_http_finalize_connection(r);
+            return;
+        }
 
         if (r->buffered || r->postponed) {
 
@@ -2374,9 +2394,6 @@ ngx_http_finalize_request(ngx_http_reque
             r->main->count--;
 
             if (!r->logged) {
-
-                clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
-
                 if (clcf->log_subrequest) {
                     ngx_http_log_request(r);
                 }
@@ -2440,6 +2457,8 @@ ngx_http_finalize_request(ngx_http_reque
     }
 
     r->done = 1;
+
+    r->read_event_handler = ngx_http_block_reading;
     r->write_event_handler = ngx_http_request_empty_handler;
 
     if (!r->post_action) {
@@ -2558,6 +2577,8 @@ ngx_http_finalize_connection(ngx_http_re
         return;
     }
 
+    r = r->main;
+
     if (r->reading_body) {
         r->keepalive = 0;
         r->lingering_close = 1;
diff -r 3e2d90073adf -r 9552758a786e src/http/ngx_http_request.h
--- a/src/http/ngx_http_request.h	Wed May 24 13:17:08 2017 +0300
+++ b/src/http/ngx_http_request.h	Thu May 25 15:57:59 2017 +0300
@@ -64,6 +64,7 @@
 #define NGX_HTTP_SUBREQUEST_IN_MEMORY      2
 #define NGX_HTTP_SUBREQUEST_WAITED         4
 #define NGX_HTTP_SUBREQUEST_CLONE          8
+#define NGX_HTTP_SUBREQUEST_BACKGROUND     16
 
 #define NGX_HTTP_LOG_UNSAFE                1
 
@@ -486,7 +487,6 @@ struct ngx_http_request_s {
 
 #if (NGX_HTTP_CACHE)
     unsigned                          cached:1;
-    unsigned                          cache_updater:1;
 #endif
 
 #if (NGX_HTTP_GZIP)
@@ -543,6 +543,7 @@ struct ngx_http_request_s {
     unsigned                          stat_writing:1;
     unsigned                          stat_processing:1;
 
+    unsigned                          background:1;
     unsigned                          health_check:1;
 
     /* used to parse HTTP headers */
diff -r 3e2d90073adf -r 9552758a786e src/http/ngx_http_upstream.c
--- a/src/http/ngx_http_upstream.c	Wed May 24 13:17:08 2017 +0300
+++ b/src/http/ngx_http_upstream.c	Thu May 25 15:57:59 2017 +0300
@@ -879,7 +879,7 @@ ngx_http_upstream_cache(ngx_http_request
     case NGX_HTTP_CACHE_STALE:
 
         if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
-             || c->stale_updating) && !r->cache_updater
+             || c->stale_updating) && !r->background
             && u->conf->cache_background_update)
         {
             r->cache->background = 1;
@@ -892,7 +892,7 @@ ngx_http_upstream_cache(ngx_http_request
     case NGX_HTTP_CACHE_UPDATING:
 
         if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
-             || c->stale_updating) && !r->cache_updater)
+             || c->stale_updating) && !r->background)
         {
             u->cache_status = rc;
             rc = NGX_OK;
@@ -1076,14 +1076,14 @@ ngx_http_upstream_cache_background_updat
     }
 
     if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL,
-                            NGX_HTTP_SUBREQUEST_CLONE)
+                            NGX_HTTP_SUBREQUEST_CLONE
+                            |NGX_HTTP_SUBREQUEST_BACKGROUND)
         != NGX_OK)
     {
         return NGX_ERROR;
     }
 
     sr->header_only = 1;
-    sr->cache_updater = 1;
 
     return NGX_OK;
 }


More information about the nginx-devel mailing list