From: Christos Tsantilas Date: Wed, 24 Dec 2014 09:20:52 +0000 (+0200) Subject: pconn_lifetime X-Git-Tag: merge-candidate-3-v1~414 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=c5c06f021dc296405b3f0f21f5998f09aa27ca1c;p=thirdparty%2Fsquid.git pconn_lifetime This patch add a new configuration option the 'pconn_lifetime' to allow users set the desired maximum lifetime of a persistent connection. When set, Squid will close a now-idle persistent connection that exceeded configured lifetime instead of moving the connection into the idle connection pool (or equivalent). No effect on ongoing/active transactions. Connection lifetime is the time period from the connection acceptance or opening time until "now". This limit is useful in environments with long-lived connections where Squid configuration or environmental factors change during a single connection lifetime. If unrestricted, some connections may last for hours and even days, ignoring those changes that should have affected their behavior or their existence. This option has the following behaviour when pipelined requests tunneled to a connection where its lifetime expired: 1. finish interpreting the Nth request check whether pconn_lifetime has expired 2. if pconn_lifetime has expired, then stop further reading and do not interpret any already read raw bytes of the N+1st request 3. otherwise, read and interpret read raw bytes of the N+1st request and go to #1. This is a Measurement Factory project --- diff --git a/src/SquidConfig.h b/src/SquidConfig.h index eea6d84354..72f0237ac8 100644 --- a/src/SquidConfig.h +++ b/src/SquidConfig.h @@ -89,6 +89,7 @@ public: time_t clientIdlePconn; time_t serverIdlePconn; time_t ftpClientIdle; + time_t pconnLifetime; ///< pconn_lifetime in squid.conf time_t siteSelect; time_t deadPeer; int icp_query; /* msec */ diff --git a/src/cf.data.pre b/src/cf.data.pre index 68f358ebd1..48c9b1720c 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -6146,6 +6146,31 @@ DOC_START request_timeout, persistent_request_timeout and quick_abort values. DOC_END +NAME: pconn_lifetime +COMMENT: time-units +TYPE: time_t +LOC: Config.Timeout.pconnLifetime +DEFAULT: 0 seconds +DOC_START + Desired maximum lifetime of a persistent connection. + When set, Squid will close a now-idle persistent connection that + exceeded configured lifetime instead of moving the connection into + the idle connection pool (or equivalent). No effect on ongoing/active + transactions. Connection lifetime is the time period from the + connection acceptance or opening time until "now". + + This limit is useful in environments with long-lived connections + where Squid configuration or environmental factors change during a + single connection lifetime. If unrestricted, some connections may + last for hours and even days, ignoring those changes that should + have affected their behavior or their existence. + + Currently, a new lifetime value supplied via Squid reconfiguration + has no effect on already idle connections unless they become busy. + + When set to '0' this limit is not used. +DOC_END + NAME: half_closed_clients TYPE: onoff LOC: Config.onoff.half_closed_clients diff --git a/src/client_side.cc b/src/client_side.cc index 03139fc366..a458fc3bcb 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1507,7 +1507,7 @@ ConnStateData::readNextRequest() typedef CommCbMemFunT TimeoutDialer; AsyncCall::Pointer timeoutCall = JobCallback(33, 5, TimeoutDialer, this, ConnStateData::requestTimeout); - commSetConnTimeout(clientConnection, idleTimeout(), timeoutCall); + commSetConnTimeout(clientConnection, clientConnection->timeLeft(idleTimeout()), timeoutCall); readSomeData(); /** Please don't do anything with the FD past here! */ @@ -3000,6 +3000,12 @@ ConnStateData::clientParseRequests() if (concurrentRequestQueueFilled()) break; + /*Do not read more requests if persistent connection lifetime exceeded*/ + if (Config.Timeout.pconnLifetime && clientConnection->lifeTime() > Config.Timeout.pconnLifetime) { + flags.readMore = false; + break; + } + // try to parse the PROXY protocol header magic bytes if (needProxyProtocolHeader_ && !parseProxyProtocolHeader()) break; diff --git a/src/client_side_reply.cc b/src/client_side_reply.cc index c18e01399c..a6f15507b7 100644 --- a/src/client_side_reply.cc +++ b/src/client_side_reply.cc @@ -1498,10 +1498,17 @@ clientReplyContext::buildReplyHeader() // The peer wants to close the pinned connection debugs(88, 3, "pinned reply forces close"); request->flags.proxyKeepalive = false; - } else if (http->getConn() && http->getConn()->port->listenConn == NULL) { - // The listening port closed because of a reconfigure - debugs(88, 3, "listening port closed"); - request->flags.proxyKeepalive = false; + } else if (http->getConn()) { + ConnStateData * conn = http->getConn(); + if (!Comm::IsConnOpen(conn->port->listenConn)) { + // The listening port closed because of a reconfigure + debugs(88, 3, "listening port closed"); + request->flags.proxyKeepalive = false; + } else if (Config.Timeout.pconnLifetime && conn->clientConnection->lifeTime() > Config.Timeout.pconnLifetime && conn->getConcurrentRequestCount() <= 1) { + // The persistent connection lifetime exceeded and we are the last parsed request + debugs(88, 3, "persistent connection lifetime exceeded"); + request->flags.proxyKeepalive = false; + } } // Decide if we send chunked reply diff --git a/src/comm/Connection.cc b/src/comm/Connection.cc index 01d204b11a..5862671745 100644 --- a/src/comm/Connection.cc +++ b/src/comm/Connection.cc @@ -13,6 +13,7 @@ #include "comm/Connection.h" #include "fde.h" #include "neighbors.h" +#include "SquidConfig.h" #include "SquidTime.h" class CachePeer; @@ -102,3 +103,12 @@ Comm::Connection::setPeer(CachePeer *p) } } +time_t +Comm::Connection::timeLeft(const time_t idleTimeout) const +{ + if (!Config.Timeout.pconnLifetime) + return idleTimeout; + + const time_t lifeTimeLeft = lifeTime() < Config.Timeout.pconnLifetime ? Config.Timeout.pconnLifetime - lifeTime() : 1; + return min(lifeTimeLeft, idleTimeout); +} diff --git a/src/comm/Connection.h b/src/comm/Connection.h index cb79405320..1e100576c1 100644 --- a/src/comm/Connection.h +++ b/src/comm/Connection.h @@ -97,6 +97,12 @@ public: /** The time the connection started */ time_t startTime() const {return startTime_;} + /** The connection lifetime */ + time_t lifeTime() const {return squid_curtime - startTime_;} + + /** The time left for this connection*/ + time_t timeLeft(const time_t idleTimeout) const; + void noteStart() {startTime_ = squid_curtime;} private: /** These objects may not be exactly duplicated. Use copyDetails() instead. */ diff --git a/src/pconn.cc b/src/pconn.cc index e4f4960bc8..bf4705525d 100644 --- a/src/pconn.cc +++ b/src/pconn.cc @@ -182,7 +182,7 @@ IdleConnList::push(const Comm::ConnectionPointer &conn) comm_read(conn, fakeReadBuf_, sizeof(fakeReadBuf_), readCall); AsyncCall::Pointer timeoutCall = commCbCall(5,4, "IdleConnList::Timeout", CommTimeoutCbPtrFun(IdleConnList::Timeout, this)); - commSetConnTimeout(conn, Config.Timeout.serverIdlePconn, timeoutCall); + commSetConnTimeout(conn, conn->timeLeft(Config.Timeout.serverIdlePconn), timeoutCall); } /// Determine whether an entry in the idle list is available for use.