]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
pconn_lifetime
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 24 Dec 2014 09:20:52 +0000 (11:20 +0200)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Wed, 24 Dec 2014 09:20:52 +0000 (11:20 +0200)
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

src/SquidConfig.h
src/cf.data.pre
src/client_side.cc
src/client_side_reply.cc
src/comm/Connection.cc
src/comm/Connection.h
src/pconn.cc

index eea6d84354a90b6bdcceef75e1abb73e10bcfb56..72f0237ac87b82770bd0d284ab98b3ac82ceb50d 100644 (file)
@@ -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 */
index 68f358ebd11668047dd9e6fb2b5a240775742f19..48c9b1720c6bddb17be9691fd4d0a9a44b7ccbe5 100644 (file)
@@ -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
index 03139fc366911291bbd8410723bdd497bebd2031..a458fc3bcb758705a805e07b1141c4869b1afd50 100644 (file)
@@ -1507,7 +1507,7 @@ ConnStateData::readNextRequest()
     typedef CommCbMemFunT<ConnStateData, CommTimeoutCbParams> 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;
index c18e01399c3a591218d953f16707293a91072a2b..a6f15507b76cfbc960376b9e13fb7f4034be17d1 100644 (file)
@@ -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
index 01d204b11aba774f37f48557fd9b1c7b4b7c13f5..58626717458652d7956f9e9bc73400531fad35db 100644 (file)
@@ -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);
+}
index cb79405320f579225ecd355278e25aa827c6d69a..1e100576c1fec26286e0e4c26208fc9ffe24699c 100644 (file)
@@ -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. */
index e4f4960bc84422e4d844ddfc6a669e92a742f9e2..bf4705525d09013e5f8b00a8ca2df47b4b2c6472 100644 (file)
@@ -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.