Android okhttp源码分析

1.OkHttp同步的使用

//如果创建创建需要很多的参数,可以使用Builder()方式
 OkHttpClient mOkHttpClient = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();
  
    public void synRequest(){
        Request  request=new Request.Builder().url("http://www.baidu.com").get().build();
        Call call=mOkHttpClient.newCall(request);
        try{
            Response response=call.execute();
            System.out.println(response.body().toString());
        }catch(Exception e){
            e.printStackTrace();
        }
    }

1看下OkHttpClient的Builder()方法,对象属性的初始化

 public Builder() {
      dispatcher = new Dispatcher(); //请求分发器,由它决定异步请求时直接处理还是缓存等待,对于同步请求没有做太多的操作
      protocols = DEFAULT_PROTOCOLS;
      connectionSpecs = DEFAULT_CONNECTION_SPECS;
      eventListenerFactory = EventListener.factory(EventListener.NONE);
      proxySelector = ProxySelector.getDefault();
      if (proxySelector == null) {
        proxySelector = new NullProxySelector();
      }
      cookieJar = CookieJar.NO_COOKIES;
      socketFactory = SocketFactory.getDefault();
      hostnameVerifier = OkHostnameVerifier.INSTANCE;
      certificatePinner = CertificatePinner.DEFAULT;
      proxyAuthenticator = Authenticator.NONE;
      authenticator = Authenticator.NONE;
      connectionPool = new ConnectionPool();//它是一个连接池,客户端和服务器之间的连接可以抽象为一个connection,每一个connection都会放在连接池中,由它来进行统一的管理,要是相同的话,可以选择复用,它可以决哪些连接是可以保持打开,哪些是可以复用的

2.看下Request请求报文的Builder()方法

public Builder() {
      this.method = "GET";
      this.headers = new Headers.Builder();
    }

3.看下Request的build()方法

public Request build() {
      if (url == null) throw new IllegalStateException("url == null");
      return new Request(this);
    }

4.根据3看下request的构造方法,方法里是有关请求信息的属性

Request(Builder builder) {
    this.url = builder.url;
    this.method = builder.method;
    this.headers = builder.headers.build();
    this.body = builder.body;
    this.tags = Util.immutableMap(builder.tags);
  }

5.看下newCall(request)方法一直跟踪到call的实现类RealCall构造方法,可以看到RealCall持有了前两步创建的OkHttpClient和Request

private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
  }

6.接下来是call.execute()

 @Override public Response execute() throws IOException {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed"); //执行过就报异常
      executed = true
    }
    transmitter.timeoutEnter();
    transmitter.callStart();
    try {
      client.dispatcher().executed(this);
      return getResponseWithInterceptorChain(); //拦截器链的操作
    } finally {
      client.dispatcher().finished(this);//主动回收同步请求
    }
  }

7.看下client.dispatcher()就返回dispatcher实例
public Dispatcher dispatcher() {
return dispatcher;
}
8.看下 client.dispatcher().executed(this); 就是在分发器里同步请求队列了添加请求

  /** Used by {@code Call#execute} to signal it is in-flight. */
  synchronized void executed(RealCall call) {
    runningSyncCalls.add(call);
  }
    /** Running synchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();

9.看下finished()方法

private <T> void finished(Deque<T> calls, T call) {
    Runnable idleCallback;
    synchronized (this) {
      if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!"); //不能移除同步请求报异常
      idleCallback = this.idleCallback;
    }

    boolean isRunning = promoteAndExecute();

    if (!isRunning && idleCallback != null) {
      idleCallback.run();
    }

注意 发送同步请求后,就会进入阻塞状态,直到收到响应

3.OkHttp异步的使用*

 OkHttpClient mOkHttpClient = new OkHttpClient.Builder().readTimeout(5, TimeUnit.SECONDS).build();

public void synRequest(){
    Request  request=new Request.Builder().url("http://www.baidu.com").get().build();
    Call call=mOkHttpClient.newCall(request);
    call.enqueue(new Callback(){//前三步都没有发起网络请求,这步才开始

        @Override
        public void onFailure(Call call, IOException e) {
            
        }

        @Override
        public void onResponse(Call call, Response response) throws IOException {
            System.out.println(response.body().toString());
        }
    });
}
1.看下enqueue()方法
  @Override public void enqueue(Callback responseCallback) {
    synchronized (this) {
      if (executed) throw new IllegalStateException("Already Executed");
      executed = true;//call只能被执行一次
    }
    transmitter.callStart();
    client.dispatcher().enqueue(new AsyncCall(responseCallback));
  }
 
2.看下client.dispatcher().enqueue(new AsyncCall(responseCallback));enqueue()方法

  void enqueue(AsyncCall call) {
    synchronized (this) {
      readyAsyncCalls.add(call);//缓存等待的队列添加异步请求

      // Mutate the AsyncCall so that it shares the AtomicInteger of an existing running call to
      // the same host.
      if (!call.get().forWebSocket) {
        AsyncCall existingCall = findExistingCallWithHost(call.host());
        if (existingCall != null) call.reuseCallsPerHostFrom(existingCall);
      }
    }
    promoteAndExecute();
  }
  /** Ready async calls in the order they'll be run. */
  private final Deque<AsyncCall> readyAsyncCalls = new ArrayDeque<>(); //缓存等待的队列

  /** Running asynchronous calls. Includes canceled calls that haven't finished yet. */
  private final Deque<AsyncCall> runningAsyncCalls = new ArrayDeque<>();  //异步队列

3.看下promoteAndExecute() 方法

 private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));

    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
      for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
        AsyncCall asyncCall = i.next();

        if (runningAsyncCalls.size() >= maxRequests) break; // 异步请求队列里请求数量要小于64.
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.

        i.remove();//遍历缓存队列,移除,添加到正在运行的队列
        asyncCall.callsPerHost().incrementAndGet();
        executableCalls.add(asyncCall);
        runningAsyncCalls.add(asyncCall);//小于64就添加到异步请求对ie
      }
      isRunning = runningCallsCount() > 0;
    }
for (int i = 0, size = executableCalls.size(); i < size; i++) {
      AsyncCall asyncCall = executableCalls.get(i);
      asyncCall.executeOn(executorService());//执行
    }

    return isRunning;
  }

 private int maxRequests = 64;
  private int maxRequestsPerHost = 5;
4.看下runningCallsCount()方法
public synchronized int runningCallsCount() {
    return runningAsyncCalls.size() + runningSyncCalls.size();//同步请求队列里请求的数量和异步请求队列里请求的数量
  }

5.看下 asyncCall.executeOn(executorService());里的executorService

 public synchronized ExecutorService executorService() { //同步
    if (executorService == null) { //保证单例
      executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,  //线程池 Integer.MAX_VALUE前面有maxRequests=64限制 参数的意义,60s后,将无关的线程关闭
          new SynchronousQueue<>(), Util.threadFactory("OkHttp Dispatcher", false));
    }
    return executorService;
  }

6.看下AsyncCall,AsyncCall就是Runnable

 final class AsyncCall extends NamedRunnable {
  public abstract class NamedRunnable implements Runnable {

7.看下asyncCall.executeOn()方法

    @Override protected void execute() {
      boolean signalledCallback = false;
      transmitter.timeoutEnter();
      try {
        Response response = getResponseWithInterceptorChain();//拦截器链
        signalledCallback = true;
        responseCallback.onResponse(RealCall.this, response);//子线程
      } catch (IOException e) {
        if (signalledCallback) {
          // Do not signal the callback twice!
          Platform.get().log(INFO, "Callback failure for " + toLoggableString(), e);
        } else {
          responseCallback.onFailure(RealCall.this, e);//子线程
        }
      } finally {
        client.dispatcher().finished(this);//1.从正在执行的异步队列中,移除当前请求 2.重新计算正在运行请求的数量
      }
    }
  }

一个异步请求执行完后,要将此请求从异步执行队列中移除
注意onFailure,onResponse方法都是在子线程中进行的

dispatcher
dispatcher的作用为维护请求的状态,并维护一个线程池,用于执行请求
dispatcher里为什么要维护两个异步请求队列
dispatcher运行在主线程的生产者
ExecutorService消费者池
Deque readyAsyncCalls缓存异步队列
Deque readyAsyncCalls正在执行的异步队列

拦截器是okhttp中提供一种强大机制,它可以实现网监听,请求以及响应重写,请求失败重功能(不区分同步异步)

Response getResponseWithInterceptorChain() throws IOException {
    // Build a full stack of interceptors.
    List<Interceptor> interceptors = new ArrayList<>();
    interceptors.addAll(client.interceptors());
    interceptors.add(new RetryAndFollowUpInterceptor(client));
    interceptors.add(new BridgeInterceptor(client.cookieJar()));
    interceptors.add(new CacheInterceptor(client.internalCache()));
    interceptors.add(new ConnectInterceptor(client));
    if (!forWebSocket) {
      interceptors.addAll(client.networkInterceptors());
    }
    interceptors.add(new CallServerInterceptor(forWebSocket));

    Interceptor.Chain chain = new RealInterceptorChain(interceptors, transmitter, null, 0,
        originalRequest, this, client.connectTimeoutMillis(),
        client.readTimeoutMillis(), client.writeTimeoutMillis());

    boolean calledNoMoreExchanges = false;
    try {
      Response response = chain.proceed(originalRequest);
1.看下 chain.proceed(originalRequest)方法
public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)
      throws IOException {
    if (index >= interceptors.size()) throw new AssertionError();

    calls++;

    // If we already have a stream, confirm that the incoming request will use it.
    if (this.exchange != null && !this.exchange.connection().supportsUrl(request.url())) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must retain the same host and port");
    }

    // If we already have a stream, confirm that this is the only call to chain.proceed().
    if (this.exchange != null && calls > 1) {
      throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
          + " must call proceed() exactly once");
    }

    // Call the next interceptor in the chain.
    RealInterceptorChain next = new RealInterceptorChain(interceptors, transmitter, exchange,
        index + 1, request, call, connectTimeout, readTimeout, writeTimeout); //从index + 1开始访问,也就是下一个拦截器开始访问,构成拦截器链
    Interceptor interceptor = interceptors.get(index);
    Response response = interceptor.intercept(next);

1.RetryAndFollowUpInterceptor拦截器 此拦截器根据需要执行重定向
看RetryAndFollowUpInterceptor的intercept方法

 @Override public Response intercept(Chain chain) throws IOException {
                                   .
                                   .
                                   .
                                     if (++followUpCount > MAX_FOLLOW_UPS) {  
        throw new ProtocolException("Too many follow-up requests: " + followUpCount);
      }

      request = followUp;
      priorResponse = response;
    }
     private static final int MAX_FOLLOW_UPS = 20; //重连次数20次

2.BridgeInterceptor拦截器
从应用程序代码到网络代码的桥梁。首先,它构建来自用户的网络请求
*请求。然后它继续呼叫网络。最后,它从网络构建用户响应回应。

  • 看BridgeInterceptor的intercept()方法
 *  `@Override public Response intercept(Chain chain) throws IOException {`
                                                  .
                                                  .
                                                  .
       if (userRequest.header("Connection") == null) {
      requestBuilder.header("Connection", "Keep-Alive");//保持连接
                                                   .
                                                   .
                                                   .
      Response networkResponse = chain.proceed(requestBuilder.build());

    HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());

    Response.Builder responseBuilder = networkResponse.newBuilder()
        .request(userRequest);

    if (transparentGzip
        && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding")) //支持gzip
        && HttpHeaders.hasBody(networkResponse)) {
      GzipSource responseBody = new GzipSource(networkResponse.body().source());
      Headers strippedHeaders = networkResponse.headers().newBuilder()
          .removeAll("Content-Encoding")
          .removeAll("Content-Length")
          .build();
      responseBuilder.headers(strippedHeaders);
      String contentType = networkResponse.header("Content-Type");
      responseBuilder.body(new RealResponseBody(contentType, -1L, Okio.buffer(responseBody)));
    }
    }
}

3.okhttp的缓存
使用

  OkHttpClient mOkHttpClient = new OkHttpClient.Builder().cache(new Cache(new File("catch"),24*1024*1024)).readTimeout(5, TimeUnit.SECONDS).build();

看下cache的put方法

 @Nullable CacheRequest put(Response response) {
    String requestMethod = response.request().method();

    if (HttpMethod.invalidatesCache(response.request().method())) {
      try {
        remove(response.request());
      } catch (IOException ignored) {
        // The cache cannot be written.
      }
      return null;
    }
    if (!requestMethod.equals("GET")) {  //不缓存get方法
      // Don't cache non-GET responses. We're technically allowed to cache
      // HEAD requests and some POST requests, but the complexity of doing
      // so is high and the benefit is low.
      return null;
    }

    if (HttpHeaders.hasVaryAll(response)) {
      return null;
    }

    Entry entry = new Entry(response); //它的实例就是要写入缓存的部分(它的源码里都是有关需要缓存的属性,被封装成了Entry)
    DiskLruCache.Editor editor = null; //okhttp的缓存技术就是使用DiskLruCache
    try {
      editor = cache.edit(key(response.request().url()));//将网络请求的url转换为对应的key(源码里是MD5加密的十六进制的表现形式)
      if (editor == null) {
        return null;
      }
      entry.writeTo(editor);//开始缓存
      return new CacheRequestImpl(editor);
    } catch (IOException e) {
      abortQuietly(editor);
      return null;
    }
  }
看下writeTo()方法

```java
    public void writeTo(DiskLruCache.Editor editor) throws IOException {
      BufferedSink sink = Okio.buffer(editor.newSink(ENTRY_METADATA));
                                  .
                                  .
                                  .

```if (isHttps()) {  //判断了是否是https请求,写入了握手的信息
        sink.writeByte('\n');
        sink.writeUtf8(handshake.cipherSuite().javaName())
            .writeByte('\n');
        writeCertList(sink, handshake.peerCertificates());
        writeCertList(sink, handshake.localCertificates());
        sink.writeUtf8(handshake.tlsVersion().javaName()).writeByte('\n');
      }
      sink.close();
    }

还有主体信息在哪缓存?看下CacheRequestImpl(final DiskLruCache.Editor editor)方法

CacheRequestImpl(final DiskLruCache.Editor editor) { //这个方法写入body信息
      this.editor = editor;
      this.cacheOut = editor.newSink(ENTRY_BODY);
      this.body = new ForwardingSink(cacheOut) { 
        @Override public void close() throws IOException {
          synchronized (Cache.this) {
            if (done) {
              return;
            }
            done = true;
            writeSuccessCount++;
          }
          super.close();
          editor.commit();
        }
      };
    }

CacheInterceptor缓存拦截器
看下intercept方法

  @Override public Response intercept(Chain chain) throws IOException {
    Response cacheCandidate = cache != null
        ? cache.get(chain.request()) //获取缓存
        : null;

    long now = System.currentTimeMillis();

    CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();//工厂方法,实例化CacheStrategy ,写入请求头的操作   
    /*
    /** CacheStrategy 缓存策略,看是从networkRequest网络请求还是cacheResponse缓存中获取Response;还可以同时使用,进行对比,选择最好的策略
    The request to send on the network, or null if this call doesn't use the network. */
  public final @Nullable Request networkRequest;

  /** The cached response to return or validate; or null if this call doesn't use a cache. */
  public final @Nullable Response cacheResponse;
    **/
    Request networkRequest = strategy.networkRequest;
    Response cacheResponse = strategy.cacheResponse;

    if (cache != null) {
      cache.trackResponse(strategy);//更新缓存指标,主要是命中率,在okhttp3.Cache的trackResponse()方法里,hitCount++表示命中了缓存
    }

    if (cacheCandidate != null && cacheResponse == null) {
      closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
    }

    // If we're forbidden from using the network and the cache is insufficient, fail.
    if (networkRequest == null && cacheResponse == null) {  //网络不好,没有缓存,构建Response,抛出504错误
      return new Response.Builder()
          .request(chain.request())
          .protocol(Protocol.HTTP_1_1)
          .code(504)
          .message("Unsatisfiable Request (only-if-cached)")
          .body(Util.EMPTY_RESPONSE)
          .sentRequestAtMillis(-1L)
          .receivedResponseAtMillis(System.currentTimeMillis())
          .build();
    }

    // If we don't need the network, we're done.
    if (networkRequest == null) {  //不需要网络,有缓存,直接返回缓存
      return cacheResponse.newBuilder()
          .cacheResponse(stripBody(cacheResponse))
          .build();
    }

    Response networkResponse = null;
    try {
      networkResponse = chain.proceed(networkRequest);//交给下一个拦截器工作
    } finally {
      // If we're crashing on I/O or otherwise, don't leak the cache body.
      if (networkResponse == null && cacheCandidate != null) {
        closeQuietly(cacheCandidate.body());
      }
    }

    // If we have a cache response too, then we're doing a conditional get.
    if (cacheResponse != null) {
      if (networkResponse.code() == HTTP_NOT_MODIFIED) { //如果响应码HTTP_NOT_MODIFIED为304,直接从缓存中读取数据
        Response response = cacheResponse.newBuilder()
            .headers(combine(cacheResponse.headers(), networkResponse.headers()))
            .sentRequestAtMillis(networkResponse.sentRequestAtMillis())
            .receivedResponseAtMillis(networkResponse.receivedResponseAtMillis())
            .cacheResponse(stripBody(cacheResponse))
            .networkResponse(stripBody(networkResponse))
            .build();
        networkResponse.body().close();

        // Update the cache after combining headers but before stripping the
        // Content-Encoding header (as performed by initContentStream()).
        cache.trackConditionalCacheHit();
        cache.update(cacheResponse, response);
        return response;
      } else {
        closeQuietly(cacheResponse.body());
      }
    }

    Response response = networkResponse.newBuilder()
        .cacheResponse(stripBody(cacheResponse))
        .networkResponse(stripBody(networkResponse))
        .build();

    if (cache != null) {
      if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {//如果有响应体,缓存策略可以缓存,直接缓存
        // Offer this request to the cache.
        CacheRequest cacheRequest = cache.put(response);
        return cacheWritingResponse(cacheRequest, response);
      }

      if (HttpMethod.invalidatesCache(networkRequest.method())) {//无效的缓存方法,移除request        
        try {
          cache.remove(networkRequest);
        } catch (IOException ignored) {
          // The cache cannot be written.
        }
      }
    }

    return response;
  }

看下CacheStrategy 的getCandidate()方法

private CacheStrategy getCandidate() {
                                 .
                                 .
                                 . 
         //写入请求头的操作                      
       if (!responseCaching.noCache() && ageMillis + minFreshMillis < freshMillis + maxStaleMillis) {
        Response.Builder builder = cacheResponse.newBuilder();
        if (ageMillis + minFreshMillis >= freshMillis) {
          builder.addHeader("Warning", "110 HttpURLConnection \"Response is stale\"");
        }
        long oneDayMillis = 24 * 60 * 60 * 1000L;
        if (ageMillis > oneDayMillis && isFreshnessLifetimeHeuristic()) {
          builder.addHeader("Warning", "113 HttpURLConnection \"Heuristic expiration\"");
        }
        return new CacheStrategy(null, builder.build());
      }
      String conditionName;
      String conditionValue;
      if (etag != null) {
        conditionName = "If-None-Match";
        conditionValue = etag;
      } else if (lastModified != null) {
        conditionName = "If-Modified-Since";
        conditionValue = lastModifiedString;
      } else if (servedDate != null) {
        conditionName = "If-Modified-Since";
        conditionValue = servedDateString;
      } else {
        return new CacheStrategy(request, null); // No condition! Make a regular request.
      }

      Headers.Builder conditionalRequestHeaders = request.headers().newBuilder();
      Internal.instance.addLenient(conditionalRequestHeaders, conditionName, conditionValue);

      Request conditionalRequest = request.newBuilder()
          .headers(conditionalRequestHeaders.build())
          .build();
      return new CacheStrategy(conditionalRequest, cacheResponse);                                                                    
    }

ConnectInterceptor网络连接拦截器
看下intercept方法

@Override public Response intercept(Chain chain) throws IOException {
                                   .
                                   .
                                   .
    Exchange exchange = transmitter.newExchange(chain, doExtensiveHealthChecks);

    return realChain.proceed(request, transmitter, exchange);
  }

看下newExchange()方法

  Exchange newExchange(Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
                                                                     .
                                                                     .
                                                                     .
 ExchangeCodec codec = exchangeFinder.find(client, chain, doExtensiveHealthChecks);
}
``
看下 exchangeFinder.find(client, chain, doExtensiveHealthChecks)方法

```java
 public ExchangeCodec find(
                                                    .
                                                    .
                                                    .
                                                    try {
      RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,//RealConnection 是核心
          writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
      return resultConnection.newCodec(client, chain);
    } catch (RouteException e) {
      trackFailure();
      throw e;
    } catch (IOException e) {
      trackFailure();
      throw new RouteException(e);
    }
  }
}

看下findHealthyConnection()方法

private RealConnection findHealthyConnection(int connectTimeout, int readTimeout,
                                                                    .
                                                                    .
                                                                    .
      synchronized (connectionPool) {
        if (candidate.successCount == 0) {  //如果successCount =0,就返回,这时候循环已结束
          return candidate;
        }
          if (!candidate.isHealthy(doExtensiveHealthChecks)) { //检查candidate是否健康(比如Socket连接没有关闭,输入输出流没有关闭,就是不健康的)
        candidate.noNewExchanges(); //如果不健康,进行资源销毁的动作
        continue;//循环调用RealConnection candidate = findConnection(connectTimeout, readTimeout, writeTimeout,
          pingIntervalMillis, connectionRetryEnabled);去寻找RealConnection 
      }

      return candidate;
    }
  }

看下 findConnection(connectTimeout, readTimeout, writeTimeout, pingIntervalMillis, connectionRetryEnabled);方法

 private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
      int pingIntervalMillis, boolean connectionRetryEnabled) throws IOException {
                                              .
                                              .
                                              .
           if (transmitter.connection != null) {

        result = transmitter.connection;  //尝试复用,赋值给result,result就是RealConnection
        releasedConnection = null;
      }
                                              .
                                              .
                                              .
      if (result == null) {
        // 如果不能复用从connectionPool连接池中获取
        if (connectionPool.transmitterAcquirePooledConnection(address, transmitter, null, false)) {
          foundPooledConnection = true;
          result = transmitter.connection;
        } else if (nextRouteToTry != null) {
          selectedRoute = nextRouteToTry;
          nextRouteToTry = null;
        } else if (retryCurrentRoute()) {
          selectedRoute = transmitter.connection.route();
        }
      }
    }
                                              .
                                              .
                                              .
       result.connect(connectTimeout, readTimeout, writeTimeout, pingIntervalMillis,//核心,获取到了RealConnection,就进行网络连接
      connectionRetryEnabled, call, eventListener);
    connectionPool.routeDatabase.connected(result.route());

    Socket socket = null;
  synchronized (connectionPool) {
      connectingConnection = null;
      // Last attempt at connection coalescing, which only occurs if we attempted multiple
      // concurrent connections to the same host.
      if (connectionPool.transmitterAcquirePooledConnection(address, transmitter, routes, true)) {
        // We lost the race! Close the connection we created and return the pooled connection.
        result.noNewExchanges = true;
        socket = result.socket();
        result = transmitter.connection;
      } else {
        connectionPool.put(result);//获取到了RealConnection,添加到连接池中
        transmitter.acquireConnectionNoEvents(result);
      }
    }
}

看下esult.connect(connectTimeout, readTimeout, writeTimeout, pingIntervalMillis,connectionRetryEnabled, call, eventListener);方法

 public void connect(int connectTimeout, int readTimeout, int writeTimeout,
      int pingIntervalMillis, boolean connectionRetryEnabled, Call call,
      EventListener eventListener) {
    if (protocol != null) throw new IllegalStateException("already connected");//核心判断有没有连接
        RouteException routeException = null;
    List<ConnectionSpec> connectionSpecs = route.address().connectionSpecs();//指定Socket连接的配置
    ConnectionSpecSelector connectionSpecSelector = new ConnectionSpecSelector(connectionSpecs);//用于选择链接(隧道链接,Socket链接)
                                              .
                                              .
                                              .
     }

RealConnectionPool连接池 作用:在它的时间范围内复用connection
看下 transmitterAcquirePooledConnection(Address address, Transmitter transmitter,@Nullable List routes, boolean requireMultiplexed) 获取链接的方法

  boolean transmitterAcquirePooledConnection(Address address, Transmitter transmitter,
      @Nullable List<Route> routes, boolean requireMultiplexed) {
    assert (Thread.holdsLock(this));
    for (RealConnection connection : connections) {
      if (requireMultiplexed && !connection.isMultiplexed()) continue;
      if (!connection.isEligible(address, routes)) continue;//判断链接是否可以使用
      transmitter.acquireConnectionNoEvents(connection);
      return true;
    }
    return false;
  }

看下transmitter.acquireConnectionNoEvents(connection)方法

void acquireConnectionNoEvents(RealConnection connection) {
    assert (Thread.holdsLock(connectionPool));

    if (this.connection != null) throw new IllegalStateException();
    this.connection = connection; //赋值
    connection.transmitters.add(new TransmitterReference(this, callStackTrace));//添加到transmitters,transmitters就是一个集合,通过集合的大小判断是否超过负载量
  }

看下put(RealConnection connection) 方法

  void put(RealConnection connection) {
    assert (Thread.holdsLock(this));
    if (!cleanupRunning) {
      cleanupRunning = true;
      executor.execute(cleanupRunnable);//执行
    }
    connections.add(connection);//添加到connections集合中
  }

看下清理线程池的代码

  private final Runnable cleanupRunnable = () -> {
    while (true) {
      long waitNanos = cleanup(System.nanoTime());//下一次需要清理间隔的时间
      if (waitNanos == -1) return;
      if (waitNanos > 0) {
        long waitMillis = waitNanos / 1000000L;
        waitNanos -= (waitMillis * 1000000L);
        synchronized (RealConnectionPool.this) {
          try {
            RealConnectionPool.this.wait(waitMillis, (int) waitNanos);//等待释放锁和时间片,当等待的时间过了之后,它会再次调用Runnable去清理,同时会返回下次需要清理的间隔时间
          } catch (InterruptedException ignored) {
          }
        }
      }
    }
  };

看下 cleanup(System.nanoTime())方法 相当于虚拟机的标记清除算法,就是标记不活跃或者长时间为使用的链接,然后进行清除

  long cleanup(long now) {
    int inUseConnectionCount = 0;
    int idleConnectionCount = 0;
    RealConnection longestIdleConnection = null;
    long longestIdleDurationNs = Long.MIN_VALUE;

    // Find either a connection to evict, or the time that the next eviction is due.
    synchronized (this) {
      for (Iterator<RealConnection> i = connections.iterator(); i.hasNext(); ) {
        RealConnection connection = i.next();

        // If the connection is in use, keep searching.
        if (pruneAndGetAllocationCount(connection, now) > 0) {//找到正在使用的链接的方法
          inUseConnectionCount++;
          continue;
        }

        idleConnectionCount++;

        // If the connection is ready to be evicted, we're done.
        long idleDurationNs = now - connection.idleAtNanos;
        if (idleDurationNs > longestIdleDurationNs) {
          longestIdleDurationNs = idleDurationNs;
          longestIdleConnection = connection;
        }
      }

      if (longestIdleDurationNs >= this.keepAliveDurationNs
          || idleConnectionCount > this.maxIdleConnections) {
        // We've found a connection to evict. Remove it from the list, then close it below (outside
        // of the synchronized block).
        connections.remove(longestIdleConnection);//空闲链接数量超过数量,就进行清除
      } else if (idleConnectionCount > 0) {
        // A connection will be ready to evict soon.
        return keepAliveDurationNs - longestIdleDurationNs;
      } else if (inUseConnectionCount > 0) {
        // All connections are in use. It'll be at least the keep alive duration 'til we run again.
        return keepAliveDurationNs;
      } else {
        // No connections, idle or in use.
        cleanupRunning = false;
        return -1;//没有需要清理的链接,跳出循环
      }
    }

    closeQuietly(longestIdleConnection.socket());

    // Cleanup again immediately.
    return 0;
  }

CallServerInterceptor拦截器,主要是向服务器发起一个真正的网络请求,接收到服务器给我们的返回响应
看下@Override public Response intercept(Chain chain) throws IOException 方法

@Override public Response intercept(Chain chain) throws IOException {
    RealInterceptorChain realChain = (RealInterceptorChain) chain;
    Exchange exchange = realChain.exchange(); //编码request,解码response
    Request request = realChain.request();

    long sentRequestMillis = System.currentTimeMillis();

    exchange.writeRequestHeaders(request);//向Socket里写入请求的头部信息

    boolean responseHeadersStarted = false;
    Response.Builder responseBuilder = null;

  if ("100-continue".equalsIgnoreCase(request.header("Expect"))) { //特殊处理,头部是否可以包含Expect: 100-continue
        exchange.flushRequest();
        responseHeadersStarted = true;
        exchange.responseHeadersStart();
        responseBuilder = exchange.readResponseHeaders(true);
      }
       if (responseBuilder == null) {
        if (request.body().isDuplex()) {
          // Prepare a duplex body so that the application can send a request body later.
          exchange.flushRequest();
          BufferedSink bufferedRequestBody = Okio.buffer(
              exchange.createRequestBody(request, true));
          request.body().writeTo(bufferedRequestBody);//向Socket里写入body信息
                                               .
                                               .
                                               .
             if (request.body() == null || !request.body().isDuplex()) {
      exchange.finishRequest();//完成整个网络请求的写入信息
    }
   
    if (responseBuilder == null) {
                                               .
                                               .
                                               .
      responseBuilder = exchange.readResponseHeaders(false);//读取网络请求的头部信息
                                               .
                                               .
                                               .
if (forWebSocket && code == 101) { //判断响应码
      // Connection is upgrading, but we need to ensure interceptors see a non-null response body.
      response = response.newBuilder()
          .body(Util.EMPTY_RESPONSE)
          .build();
    } else {
      response = response.newBuilder()  //构建response
          .body(exchange.openResponseBody(response))
          .build();
    }
        if ("close".equalsIgnoreCase(response.request().header("Connection"))
        || "close".equalsIgnoreCase(response.header("Connection"))) {
      exchange.noNewExchangesOnConnection();//关闭流,关闭链接


    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值