1 public abstract class PoolEntry<T, C> { 2 3 private final String id; 4 private final T route; //Route 5 private final C conn; //http connection 6 private final long created; //Creation time 7 private final long validityDeadline; 8 9 private long updated; 10 11 private long expiry; 12 13 private volatile Object state; 14 15 }
Construction method:
1 public PoolEntry(final String id, final T route, final C conn, 2 final long timeToLive, final TimeUnit tunit) { 3 super(); 4 Args.notNull(route, "Route"); 5 Args.notNull(conn, "Connection"); 6 Args.notNull(tunit, "Time unit"); 7 this.id = id; 8 this.route = route; 9 this.conn = conn; 10 this.created = System.currentTimeMillis(); 11 this.updated = this.created; 12 if (timeToLive > 0) { 13 final long deadline = this.created + tunit.toMillis(timeToLive); 14 // If the above overflows then default to Long.MAX_VALUE 15 this.validityDeadline = deadline > 0 ? deadline : Long.MAX_VALUE; 16 } else { 17 this.validityDeadline = Long.MAX_VALUE; 18 } 19 this.expiry = this.validityDeadline; 20 }
Update expires:
1 public synchronized void updateExpiry(final long time, final TimeUnit tunit) { 2 Args.notNull(tunit, "Time unit"); 3 this.updated = System.currentTimeMillis(); 4 final long newExpiry; 5 if (time > 0) { 6 newExpiry = this.updated + tunit.toMillis(time); 7 } else { 8 newExpiry = Long.MAX_VALUE; 9 } 10 this.expiry = Math.min(newExpiry, this.validityDeadline); 11 }
1. The http connection pool manages a connection object. In fact, it manages a PoolEntry instance;
2. When to update the PoolEntry instance information, such as expiration time and status?
Instance information will be updated when the connection is released;
Specifically, it is called in PoolingHttpClientConnectionManager.releaseConnection(final HttpClientConnection managedConn, final Object state, final long keepalive, final keepalive) method, but this method is what we are releasing.
1 public void releaseConnection( 2 final HttpClientConnection managedConn, 3 final Object state, 4 final long keepalive, final TimeUnit tunit) { 5 Args.notNull(managedConn, "Managed connection"); 6 synchronized (managedConn) { 7 final CPoolEntry entry = CPoolProxy.detach(managedConn); 8 if (entry == null) { 9 return; 10 } 11 final ManagedHttpClientConnection conn = entry.getConnection(); 12 try { 13 if (conn.isOpen()) { 14 final TimeUnit effectiveUnit = tunit != null ? tunit : TimeUnit.MILLISECONDS; 15 entry.setState(state); 16 entry.updateExpiry(keepalive, effectiveUnit); //The keepalive parameter indicates the expiration time of a long connection, which is set by the keepAliveStrategy parameter on the client side 17 if (this.log.isDebugEnabled()) { 18 final String s; 19 if (keepalive > 0) { 20 s = "for " + (double) effectiveUnit.toMillis(keepalive) / 1000 + " seconds"; 21 } else { 22 s = "indefinitely"; 23 } 24 this.log.debug("Connection " + format(entry) + " can be kept alive " + s); 25 } 26 conn.setSocketTimeout(0); 27 } 28 } finally { 29 this.pool.release(entry, conn.isOpen() && entry.isRouteComplete()); 30 if (this.log.isDebugEnabled()) { 31 this.log.debug("Connection released: " + format(entry) + formatStats(entry.getRoute())); 32 } 33 } 34 } 35 }
3. PoolingHttpClientConnectionManager connection pool parameter validateAfterInactivity Description:
When a poolentry is obtained from the connection pool, if the validateafteractivity parameter is greater than 0 and the updated and validateafteractivity of the poolentry instance is less than or equal to the current time, the connection state state value of the connection (con in the httpEntry instance) will be checked;
1 org.apache.http.impl.BHttpConnectionBase 2 public boolean isStale() { 3 if (!isOpen()) { 4 return true; 5 } 6 try { 7 final int bytesRead = fillInputBuffer(1); 8 return bytesRead < 0; 9 } catch (final SocketTimeoutException ex) { 10 return false; 11 } catch (final IOException ex) { 12 return true; 13 } 14 }
4. Closing idle timeout connection method of PoolingHttpClientConnectionManager:
The update time plus idle time (setting) of the PoolEntry instance is greater than or equal to the current time, indicating that the connection exceeds the idle time
1 public void closeIdleConnections(final long idleTimeout, final TimeUnit tunit) { 2 if (this.log.isDebugEnabled()) { 3 this.log.debug("Closing connections idle longer than " + idleTimeout + " " + tunit); 4 } 5 this.pool.closeIdle(idleTimeout, tunit); 6 }
5. Closing overdue connection method of PoolingHttpClientConnectionManager:
Indicates that the current time is greater than the expiry value of the PoolEntry instance
1 public void closeExpiredConnections() { 2 this.log.debug("Closing expired connections"); 3 this.pool.closeExpired(); 4 }
6. closeIdleConnections() and closeExpiredConnections() are provided externally, which need to be called by users themselves. We usually maintain an independent thread to call, and clear the idle and expired connections.