Opened 5 years ago

Closed 5 years ago

#1937 closed defect (worksforme)

Nginx didn't update cache anymore after ngx_http_upstream_cache_background_update is failed.

Reported by: haosdent@… Owned by:
Priority: major Milestone: nginx-1.17
Component: documentation Version: 1.16.x
Keywords: Cc:
uname -a:
nginx -V: nginx version: nginx/1.14.0
built by gcc 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.11)
built with OpenSSL 1.0.2j 26 Sep 2016
TLS SNI support enabled

Description

When I use

    proxy_cache_background_update  on;
    proxy_cache_use_stale          updating;

I found after the background subrequest is failed once, Nginx would not update cache anymore even the upstream recover.

This is due to once the background subrequest is failed.

    switch (rc) {

    case NGX_HTTP_CACHE_STALE:

        if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
             || c->stale_updating) && !r->background
            && u->conf->cache_background_update)
        {
            r->cache->background = 1;
            u->cache_status = rc;
            rc = NGX_OK;
        }

        break;

    case NGX_HTTP_CACHE_UPDATING:

        if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
             || c->stale_updating) && !r->background)
        {
            u->cache_status = rc;
            rc = NGX_OK;

        } else {
            rc = NGX_HTTP_CACHE_STALE;
        }

cache status would become NGX_HTTP_CACHE_UPDATING, and because Nginx didn't set r->cache->background = 1 again if cache status is NGX_HTTP_CACHE_UPDATING. Then in ngx_http_upstream_cache_background_update, it return directly for all further background subrequests.

static ngx_int_t
ngx_http_upstream_cache_background_update(ngx_http_request_t *r,
    ngx_http_upstream_t *u)
{
    ngx_http_request_t  *sr;

    if (!r->cached || !r->cache->background) {
        return NGX_OK;
    }



This make Nginx always return stale content.

To fix this, we need to

  • src/http/ngx_http_upstream.c

    diff --git a/src/http/ngx_http_upstream.c b/src/http/ngx_http_upstream.c
    index a1647e9d..1a0cbeec 100644
    a b ngx_http_upstream_cache(ngx_http_request_t *r, ngx_http_upstream_t *u)  
    967967        if (((u->conf->cache_use_stale & NGX_HTTP_UPSTREAM_FT_UPDATING)
    968968             || c->stale_updating) && !r->background)
    969969        {
     970            r->cache->background = 1;
    970971            u->cache_status = rc;
    971972            rc = NGX_OK;

Change History (2)

comment:1 by Maxim Dounin, 5 years ago

The NGX_HTTP_CACHE_UPDATING return code is only expected to be returned as long as there is an update request in progress. This is designed to make sure only one request will be used to update the cache element, see proxy_cache_use_stale updating docs. As such, it is clearly wrong to set r->cache->background when ngx_http_file_cache_open() returns NGX_HTTP_CACHE_UPDATING.

If you observe that NGX_HTTP_CACHE_UPDATING is incorrectly returned after an update request failure, please provide more details.

comment:2 by Maxim Dounin, 5 years ago

Resolution: worksforme
Status: newclosed

Feedback timeout.

Note: See TracTickets for help on using tickets.