From: Eduard Bagdasaryan Date: Sat, 12 Mar 2016 20:27:35 +0000 (-0700) Subject: Author: Eduard Bagdasaryan X-Git-Tag: SQUID_4_0_8~35 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=afc753f36750559063280f2755a281fb721e2cb3;p=thirdparty%2Fsquid.git Author: Eduard Bagdasaryan Added ACL-driven server_pconn_for_nonretriable squid.conf directive. This directive provides fine-grained control over persistent connection reuse when forwarding HTTP requests that Squid cannot retry. It is useful in environments where opening new connections is very expensive and race conditions associated with persistent connections are very rare and/or only cause minor problems. --- diff --git a/src/FwdState.cc b/src/FwdState.cc index a4e860dc36..fa0b3ffae4 100644 --- a/src/FwdState.cc +++ b/src/FwdState.cc @@ -589,14 +589,7 @@ FwdState::checkRetry() return true; } -/* - * FwdState::checkRetriable - * - * Return TRUE if this is the kind of request that can be retried - * after a failure. If the request is not retriable then we don't - * want to risk sending it on a persistent connection. Instead we'll - * force it to go on a new HTTP connection. - */ +/// Whether we may try sending this request again after a failure. bool FwdState::checkRetriable() { @@ -1188,9 +1181,14 @@ FwdState::pconnPush(Comm::ConnectionPointer &conn, const char *domain) Comm::ConnectionPointer FwdState::pconnPop(const Comm::ConnectionPointer &dest, const char *domain) { + bool retriable = checkRetriable(); + if (!retriable && Config.accessList.serverPconnForNonretriable) { + ACLFilledChecklist ch(Config.accessList.serverPconnForNonretriable, request, NULL); + retriable = (ch.fastCheck() == ACCESS_ALLOWED); + } // always call shared pool first because we need to close an idle // connection there if we have to use a standby connection. - Comm::ConnectionPointer conn = fwdPconnPool->pop(dest, domain, checkRetriable()); + Comm::ConnectionPointer conn = fwdPconnPool->pop(dest, domain, retriable); if (!Comm::IsConnOpen(conn)) { // either there was no pconn to pop or this is not a retriable xaction if (CachePeer *peer = dest->getPeer()) { diff --git a/src/SquidConfig.h b/src/SquidConfig.h index 0a0689e482..59ea1cebc4 100644 --- a/src/SquidConfig.h +++ b/src/SquidConfig.h @@ -394,6 +394,7 @@ public: acl_access *ftp_epsv; acl_access *forceRequestBodyContinuation; + acl_access *serverPconnForNonretriable; } accessList; AclDenyInfoList *denyInfoList; diff --git a/src/cf.data.pre b/src/cf.data.pre index bd66346231..430e77e51b 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -9632,4 +9632,42 @@ DOC_START that the request body is needed. Delaying is the default behavior. DOC_END +NAME: server_pconn_for_nonretriable +TYPE: acl_access +DEFAULT: none +DEFAULT_DOC: Open new connections for forwarding requests Squid cannot retry safely. +LOC: Config.accessList.serverPconnForNonretriable +DOC_START + This option provides fine-grained control over persistent connection + reuse when forwarding HTTP requests that Squid cannot retry. It is useful + in environments where opening new connections is very expensive + (e.g., all connections are secured with TLS with complex client and server + certificate validation) and race conditions associated with persistent + connections are very rare and/or only cause minor problems. + + HTTP prohibits retrying unsafe and non-idempotent requests (e.g., POST). + Squid limitations also prohibit retrying all requests with bodies (e.g., PUT). + By default, when forwarding such "risky" requests, Squid opens a new + connection to the server or cache_peer, even if there is an idle persistent + connection available. When Squid is configured to risk sending a non-retriable + request on a previously used persistent connection, and the server closes + the connection before seeing that risky request, the user gets an error response + from Squid. In most cases, that error response will be HTTP 502 (Bad Gateway) + with ERR_ZERO_SIZE_OBJECT or ERR_WRITE_ERROR (peer connection reset) error detail. + + If an allow rule matches, Squid reuses an available idle persistent connection + (if any) for the request that Squid cannot retry. If a deny rule matches, then + Squid opens a new connection for the request that Squid cannot retry. + + This option does not affect requests that Squid can retry. They will reuse idle + persistent connections (if any). + + This clause only supports fast acl types. + See http://wiki.squid-cache.org/SquidFaq/SquidAcl for details. + + Example: + acl SpeedIsWorthTheRisk method POST + server_pconn_for_nonretriable allow SpeedIsWorthTheRisk +DOC_END + EOF