1 public abstract class PoolEntry<T, C> {
 2 
 3     private final String id;
 4     private final T route;  //路由
 5     private final C conn;  //http连接
 6     private final long created;  //创建时间
 7     private final long validityDeadline;
 8 
 9     private long updated;
10 
11     private long expiry;
12 
13     private volatile Object state;
14 
15 }

构造方法:

 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     }

更新过期时间:

 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、http连接池管理一个连接对象,其实管理的是一个PoolEntry实例;

2、什么时候更新PoolEntry实例信息,比如过期时间,状态等?

  在释放连接的时候会更新实例信息;

  具体在:PoolingHttpClientConnectionManager.releaseConnection(final HttpClientConnection managedConn, final Object state, final long keepalive, final TimeUnit tunit) 方法中调用;但是这个方法是我们在释放response是调用的。

 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);  //keepalive 参数表示长连接的过期时间,在客户端通过keepAliveStrategy参数设置
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 连接池参数 validateAfterInactivity说明:

  当从连接池中拿到一个poolEntry时,如果validateAfterInactivity参数大于0 且 这个PoolEntry实例的updated加validateAfterInactivity小于等于当前时间,会检查这个连接(httpEntry实例中的con)的连接状态 state 值;

 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、PoolingHttpClientConnectionManager 的关闭空闲超时连接方法:

  指PoolEntry实例的更新时间加 空闲时间(设置)大于等于 当前时间,表示这个连接超过空闲时间

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、PoolingHttpClientConnectionManager 的关闭过期连接方法:

  指当前时间大于PoolEntry实例的expiry

1     public void closeExpiredConnections() {
2         this.log.debug("Closing expired connections");
3         this.pool.closeExpired();
4     }

6、closeIdleConnections() 和 closeExpiredConnections() 对外提供,需要用户自己去调用,我们一般维护一个独立的线程去调用,清除空闲的连接和过期连接。

 

posted on 2019-04-25 14:47  布咚嘞  阅读(379)  评论(0编辑  收藏  举报