Skip to content

Commit

Permalink
Background subrequests for cache updates.
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
arut committed May 25, 2017
1 parent c83922b commit 8644d94
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 24 deletions.
35 changes: 19 additions & 16 deletions src/http/ngx_http_core_module.c
Original file line number Diff line number Diff line change
Expand Up @@ -2518,6 +2518,7 @@ ngx_http_subrequest(ngx_http_request_t *r,

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;
Expand All @@ -2531,29 +2532,31 @@ ngx_http_subrequest(ngx_http_request_t *r,
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;
}
if (!sr->background) {
if (c->data == r && r->postponed == NULL) {
c->data = sr;
}

pr->request = sr;
pr->out = NULL;
pr->next = NULL;
pr = ngx_palloc(r->pool, sizeof(ngx_http_postponed_request_t));
if (pr == NULL) {
return NGX_ERROR;
}

if (r->postponed) {
for (p = r->postponed; p->next; p = p->next) { /* void */ }
p->next = pr;
pr->request = sr;
pr->out = NULL;
pr->next = NULL;

} else {
r->postponed = pr;
if (r->postponed) {
for (p = r->postponed; p->next; p = p->next) { /* void */ }
p->next = pr;

} else {
r->postponed = pr;
}
}

sr->internal = 1;
Expand Down
27 changes: 24 additions & 3 deletions src/http/ngx_http_request.c
Original file line number Diff line number Diff line change
Expand Up @@ -2357,6 +2357,26 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
}

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) {

Expand All @@ -2374,9 +2394,6 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
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);
}
Expand Down Expand Up @@ -2440,6 +2457,8 @@ ngx_http_finalize_request(ngx_http_request_t *r, ngx_int_t rc)
}

r->done = 1;

r->read_event_handler = ngx_http_block_reading;
r->write_event_handler = ngx_http_request_empty_handler;

if (!r->post_action) {
Expand Down Expand Up @@ -2558,6 +2577,8 @@ ngx_http_finalize_connection(ngx_http_request_t *r)
return;
}

r = r->main;

if (r->reading_body) {
r->keepalive = 0;
r->lingering_close = 1;
Expand Down
3 changes: 2 additions & 1 deletion src/http/ngx_http_request.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 */
Expand Down
8 changes: 4 additions & 4 deletions src/http/ngx_http_upstream.c
Original file line number Diff line number Diff line change
Expand Up @@ -879,7 +879,7 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
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;
Expand All @@ -892,7 +892,7 @@ ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)
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;
Expand Down Expand Up @@ -1076,14 +1076,14 @@ ngx_http_upstream_cache_background_update(ngx_http_request_t *r,
}

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;
}
Expand Down

0 comments on commit 8644d94

Please sign in to comment.