okhttp——3. 连接池复用

Connection

首先看一下okhttp如何定义连接,Connection接口可略知一二

public interface Connection {
  /** Returns the route used by this connection. */
  Route route();

  /**
   * Returns the socket that this connection is using. Returns an {@linkplain
   * javax.net.ssl.SSLSocket SSL socket} if this connection is HTTPS. If this is an HTTP/2
   * connection the socket may be shared by multiple concurrent calls.
   */
  Socket socket();

  /**
   * Returns the TLS handshake used to establish this connection, or null if the connection is not
   * HTTPS.
   */
  @Nullable Handshake handshake();

  /**
   * Returns the protocol negotiated by this connection, or {@link Protocol#HTTP_1_1} if no protocol
   * has been negotiated. This method returns {@link Protocol#HTTP_1_1} even if the remote peer is
   * using {@link Protocol#HTTP_1_0}.
   */
  Protocol protocol();
}

在okhttp中实现了Connection接口的类是RealConnection, 里面涉及到了如何建立一次连接。

ConnectionPool

该类用于管理所有网络请求的连接,对于满足特定条件的连接进行复用。

  1. 构造函数:
// maxIdleConnections: 单个url最大的连接数 
// keepAliveDuration: 单个连接的有效期  timeUnit: 有效期的时间单位

public ConnectionPool(int maxIdleConnections, long keepAliveDuration, TimeUnit timeUnit) {
    this.maxIdleConnections = maxIdleConnections;
    this.keepAliveDurationNs = timeUnit.toNanos(keepAliveDuration);

    // Put a floor on the keep alive duration, otherwise cleanup will spin loop.
    if (keepAliveDuration <= 0) {
      throw new IllegalArgumentException("keepAliveDuration <= 0: " + keepAliveDuration);
    }
  }

  // okhttp 使用如下默认值
  public ConnectionPool() {
    this(5, 5, TimeUnit.MINUTES);
  }

ConnectionPool 的构造只会在OkhttpClient的Builder里面创建一次,其它所有类持有的ConnectionPool都是通过参数传递过去的。

重要成员:

// 用于存放连接的双向队列
private final Deque<RealConnection> connections = new ArrayDeque<>();

获取可重用的连接

 /**
   * Returns a recycled connection to {@code address}, or null if no such connection exists. The
   * route is null if the address has not yet been routed.
   */
  @Nullable RealConnection get(Address address, StreamAllocation streamAllocation, Route route) {
    assert (Thread.holdsLock(this));
    for (RealConnection connection : connections) {
      if (connection.isEligible(address, route)) {
        streamAllocation.acquire(connection);
        return connection;
      }
    }
    return null;
  }
posted @ 2021-11-06 15:42  NeilZhang  阅读(2675)  评论(0编辑  收藏  举报