squid-2481

Version:

2.7.S3

Bug link:

http://bugs.squid-cache.org/show_bug.cgi?id=2481

Symptom (Failure):
When setting two squid servers working as parent-cache peers, child with the setting: negative_ttl -- which is to cache any ‘negative’ response (non-successful responses). However, ‘negative_ttl’ simply didn’t work. When origin server returns 504 as HTTP status, the child server never cache the response, but instead directly contact the parent server.

How it is diagnosed:

We reproduced the failure!

How to reproduce?

It is not very easy to reproduce, since it requires the original server to send a 504 response. We used the server simulator at that can send arbitrary http response. The simulator can be found at:

http://opera.ucsd.edu/errlog/mykeyboard

We also configured two squid servers, one as parent one as child. The parent uses normal configuration.

The child:

squid.conf:

cache_peer localhost       parent    3129  0 no-query

# This is to set a parent squid that is on the same machine, port 3129.

negative_ttl 1 minutes

Root Cause:

Upon receiving a 504 status, the child server sends an “Expires: current_time” header to the client, causing the client asking a fresh result everytime.

--- src/errorpage.c        15 Aug 2008 04:56:00 -0000        1.194

+++ src/errorpage.c        7 Oct 2008 21:30:17 -0000

@@ -636,7 +636,7 @@ errorBuildReply(ErrorState * err)

        MemBuf content = errorBuildContent(err);

-        httpReplySetHeaders(rep, err->http_status, NULL, "text/html", content.size, -1, squid_curtime);

+        httpReplySetHeaders(rep, err->http_status, NULL, "text/html", content.size, -1, -1);

}

/* This is called when the child Squid received the 504 response from the parent cache*/

httpMaybeRemovePublic(StoreEntry * e, http_status status) {

   … ...

   switch (status) {

   case HTTP_OK:

   case HTTP_NON_AUTHORITATIVE_INFORMATION:

   case HTTP_MULTIPLE_CHOICES:

   case HTTP_MOVED_PERMANENTLY:

   case HTTP_MOVED_TEMPORARILY:

   case HTTP_GONE:

   case HTTP_NOT_FOUND:

        remove = 1;

        break;

   case HTTP_FORBIDDEN:

   case HTTP_METHOD_NOT_ALLOWED:

        forbidden = 1;

        break;

   default:

/* status == HTTP_GATEWAY_TIMEOUT falls through, they should log here! */

        /*

         * Any 2xx response should eject previously cached entities...

         */

        if (status >= 200 && status < 300)

            remove = 1;

           break;

   }

}

Information needed to diagnose the failure:

The 504 status was returned from the backend server.

Is there any log message?:

No.

Can developers/Errlog anticipate?

Yes. This is the general “Default-Switch” pattern.