Ticket #1249: bgsub

File bgsub, 6.2 KB (added by Roman Arutyunyan, 9 years ago)
Line 
1# HG changeset patch
2# User Roman Arutyunyan <arut@nginx.com>
3# Date 1491238449 -10800
4# Mon Apr 03 19:54:09 2017 +0300
5# Node ID 629cb53e0ad84337c933599edc50d38b2ddf5c12
6# Parent 3ff293cfdab85082a9560ab56ea9f16b02a8a8c8
7Background subrequests for cache updates.
8
9Previously, cache background update might not work as expected, making client
10wait for it to complete before receiving the final part of stale response.
11This could happen if the response could not be sent to the client socket in one
12filter chain call.
13
14Now background cache update is done in a background subrequest. This type of
15subrequest does not block any other subrequests or the main request.
16
17diff --git a/src/http/ngx_http_core_module.c b/src/http/ngx_http_core_module.c
18--- a/src/http/ngx_http_core_module.c
19+++ b/src/http/ngx_http_core_module.c
20@@ -2516,6 +2516,7 @@ ngx_http_subrequest(ngx_http_request_t *
21
22 sr->subrequest_in_memory = (flags & NGX_HTTP_SUBREQUEST_IN_MEMORY) != 0;
23 sr->waited = (flags & NGX_HTTP_SUBREQUEST_WAITED) != 0;
24+ sr->background = (flags & NGX_HTTP_SUBREQUEST_BACKGROUND) != 0;
25
26 sr->unparsed_uri = r->unparsed_uri;
27 sr->method_name = ngx_http_core_get_method;
28@@ -2529,29 +2530,31 @@ ngx_http_subrequest(ngx_http_request_t *
29 sr->read_event_handler = ngx_http_request_empty_handler;
30 sr->write_event_handler = ngx_http_handler;
31
32- if (c->data == r && r->postponed == NULL) {
33- c->data = sr;
34- }
35-
36 sr->variables = r->variables;
37
38 sr->log_handler = r->log_handler;
39
40- pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
41- if (pr == NULL) {
42- return NGX_ERROR;
43- }
44-
45- pr->request = sr;
46- pr->out = NULL;
47- pr->next = NULL;
48-
49- if (r->postponed) {
50- for (p = r->postponed; p->next; p = p->next) { /* void */ }
51- p->next = pr;
52-
53- } else {
54- r->postponed = pr;
55+ if (!sr->background) {
56+ if (c->data == r && r->postponed == NULL) {
57+ c->data = sr;
58+ }
59+
60+ pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
61+ if (pr == NULL) {
62+ return NGX_ERROR;
63+ }
64+
65+ pr->request = sr;
66+ pr->out = NULL;
67+ pr->next = NULL;
68+
69+ if (r->postponed) {
70+ for (p = r->postponed; p->next; p = p->next) { /* void */ }
71+ p->next = pr;
72+
73+ } else {
74+ r->postponed = pr;
75+ }
76 }
77
78 sr->internal = 1;
79diff --git a/src/http/ngx_http_request.c b/src/http/ngx_http_request.c
80--- a/src/http/ngx_http_request.c
81+++ b/src/http/ngx_http_request.c
82@@ -2347,6 +2347,26 @@ ngx_http_finalize_request(ngx_http_reque
83 }
84
85 if (r != r->main) {
86+ clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
87+
88+ if (r->background) {
89+ if (!r->logged) {
90+ if (clcf->log_subrequest) {
91+ ngx_http_log_request(r);
92+ }
93+
94+ r->logged = 1;
95+
96+ } else {
97+ ngx_log_error(NGX_LOG_ALERT, c->log, 0,
98+ "subrequest: \"%V?%V\" logged again",
99+ &r->uri, &r->args);
100+ }
101+
102+ r->done = 1;
103+ ngx_http_finalize_connection(r);
104+ return;
105+ }
106
107 if (r->buffered || r->postponed) {
108
109@@ -2364,9 +2384,6 @@ ngx_http_finalize_request(ngx_http_reque
110 r->main->count--;
111
112 if (!r->logged) {
113-
114- clcf = ngx_http_get_module_loc_conf(r, ngx_http_core_module);
115-
116 if (clcf->log_subrequest) {
117 ngx_http_log_request(r);
118 }
119@@ -2430,6 +2447,8 @@ ngx_http_finalize_request(ngx_http_reque
120 }
121
122 r->done = 1;
123+
124+ r->read_event_handler = ngx_http_block_reading;
125 r->write_event_handler = ngx_http_request_empty_handler;
126
127 if (!r->post_action) {
128@@ -2548,6 +2567,8 @@ ngx_http_finalize_connection(ngx_http_re
129 return;
130 }
131
132+ r = r->main;
133+
134 if (r->reading_body) {
135 r->keepalive = 0;
136 r->lingering_close = 1;
137diff --git a/src/http/ngx_http_request.h b/src/http/ngx_http_request.h
138--- a/src/http/ngx_http_request.h
139+++ b/src/http/ngx_http_request.h
140@@ -63,6 +63,7 @@
141 #define NGX_HTTP_SUBREQUEST_IN_MEMORY 2
142 #define NGX_HTTP_SUBREQUEST_WAITED 4
143 #define NGX_HTTP_SUBREQUEST_CLONE 8
144+#define NGX_HTTP_SUBREQUEST_BACKGROUND 16
145
146 #define NGX_HTTP_LOG_UNSAFE 1
147
148@@ -482,7 +483,6 @@ struct ngx_http_request_s {
149
150 #if (NGX_HTTP_CACHE)
151 unsigned cached:1;
152- unsigned cache_updater:1;
153 #endif
154
155 #if (NGX_HTTP_GZIP)
156@@ -539,6 +539,7 @@ struct ngx_http_request_s {
157 unsigned stat_writing:1;
158 unsigned stat_processing:1;
159
160+ unsigned background:1;
161 unsigned health_check:1;
162
163 /* used to parse HTTP headers */
164diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
165--- a/src/http/ngx_http_upstream.c
166+++ b/src/http/ngx_http_upstream.c
167@@ -878,7 +878,7 @@ ngx_http_upstream_cache(ngx_http_request
168 case NGX_HTTP_CACHE_STALE:
169
170 if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
171- || c->stale_updating) && !r->cache_updater
172+ || c->stale_updating) && !r->background
173 && u->conf->cache_background_update)
174 {
175 r->cache->background = 1;
176@@ -891,7 +891,7 @@ ngx_http_upstream_cache(ngx_http_request
177 case NGX_HTTP_CACHE_UPDATING:
178
179 if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
180- || c->stale_updating) && !r->cache_updater)
181+ || c->stale_updating) && !r->background)
182 {
183 u->cache_status = rc;
184 rc = NGX_OK;
185@@ -1075,14 +1075,14 @@ ngx_http_upstream_cache_background_updat
186 }
187
188 if (ngx_http_subrequest(r, &r->uri, &r->args, &sr, NULL,
189- NGX_HTTP_SUBREQUEST_CLONE)
190+ NGX_HTTP_SUBREQUEST_CLONE
191+ |NGX_HTTP_SUBREQUEST_BACKGROUND)
192 != NGX_OK)
193 {
194 return NGX_ERROR;
195 }
196
197 sr->header_only = 1;
198- sr->cache_updater = 1;
199
200 return NGX_OK;
201 }