个人随记:OKHttp源码浅析

185 阅读14分钟

以下就是OKHttp的一个普通流程:

boolean isAsync = true;
OkHttpClient cilent = new OkHttpClient.Builder().build();
Call call = cilent.newCall(new Request.Builder().url("").get().build());
try {
    if(isAsync){
        call.enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                
            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

            }
        });
    }else{
        Response response = call.execute();
    }
} catch (IOException e) {
    e.printStackTrace();
}

首先初始化OKHttpCilent,直接看Build()方法:

OKHttpCilent:
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();
  dns = Dns.SYSTEM;
  followSslRedirects = true;
  followRedirects = true;
  retryOnConnectionFailure = true;
  callTimeout = 0;
  connectTimeout = 10_000;
  readTimeout = 10_000;
  writeTimeout = 10_000;
  pingInterval = 0;
}

public OkHttpClient build() {
  return new OkHttpClient(this);
}

初始化okHttp需要用到的一些对象,以及各类超时时间,如果没有指定,就按照这些默认的初始化。

然后构造出okHttpCilent通过newCall构造出Call对象:

OKHttpCilent:
@Override public Call newCall(Request request) {
    return RealCall.newRealCall(this, request, false /* for web socket */);
}

RealCall:
static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.
    RealCall call = new RealCall(client, originalRequest, forWebSocket);
    call.eventListener = client.eventListenerFactory().create(call);
    return call;
}
private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
  this.client = client;
  this.originalRequest = originalRequest;
  this.forWebSocket = forWebSocket;
  this.retryAndFollowUpInterceptor = new RetryAndFollowUpInterceptor(client, forWebSocket);
 
 //超时,工具调用超时跨越整个调用:解析DNS,连接,写请求,主体,服务器处理,并读取响应主体。
 //如果调用需要重定向或所有重试必须在一个超时时间内完成,否则到时间就会调用cancel方法。
 //默认为0,不超时
  this.timeout = new AsyncTimeout() {
    @Override protected void timedOut() {
      cancel();
    }
  };
  this.timeout.timeout(client.callTimeoutMillis(), MILLISECONDS);
}

realCall构造方法三个参数,分别是OkHttpCilent对象,Request对象以及是否websocket请求,这里普通请求为false。(如果使用cilent.newWebSocket方法后面后会构造RealCall对象,并且forWebSocket会传入true)。同时这里会创建call的回调eventListener:

EventListener:
public static final EventListener NONE = new EventListener() {
};

static EventListener.Factory factory(final EventListener listener) {
  return new EventListener.Factory() {
    public EventListener create(Call call) {
      return listener;
    }
  };
}

上面OkHttpCilent.Build()默认传入的就是NONE对象,用户可自己指定实现,主要call的各类执行过程回调。

RealCall对象创造好后,就可以执行请求方法了,可以同步也可以异步,先看同步方法:

RealCall:
@Override public Response execute() throws IOException {
  //标记已经执行,防止重复执行
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();

  //超时开始计算
  timeout.enter();
  eventListener.callStart(this);
  try {
    //将call对象加入到Dispatcher的runningSyncCalls(同步队列)中
    //Dispatcher对象已经在OkHttpClient.Build()中创建了
    client.dispatcher().executed(this);
     
    //开始责任链执行请求
    Response result = getResponseWithInterceptorChain();
    if (result == null) throw new IOException("Canceled");
    return result;
  } catch (IOException e) {
    e = timeoutExit(e);
    eventListener.callFailed(this, e);
    throw e;
  } finally {
    //结束该call,分析见下面异步finish方法
    client.dispatcher().finished(this);
  }
}
Dispatcher:
synchronized void executed(RealCall call) {
  runningSyncCalls.add(call);
}

异步请求方法:

RealCall:
@Override public void enqueue(Callback responseCallback) {
  //标记已经执行,防止重复执行
  synchronized (this) {
    if (executed) throw new IllegalStateException("Already Executed");
    executed = true;
  }
  captureCallStackTrace();
  eventListener.callStart(this);

  //将realCall包装成AsynCall(线程),放入Dispatcher中的readyAsyncCalls中(异步等待队列)
  client.dispatcher().enqueue(new AsyncCall(responseCallback));
}
Dispatcher:
void enqueue(AsyncCall call) {
    synchronized (this) {
        readyAsyncCalls.add(call);
    }
    promoteAndExecute();
}

//循环遍历等待异步队列,取出可执行的异步call
private boolean promoteAndExecute() {
    assert (!Thread.holdsLock(this));
     
    //存放从等待队列中取出的可以执行的异步call
    List<AsyncCall> executableCalls = new ArrayList<>();
    boolean isRunning;
    synchronized (this) {
        //如果runningAsyncCalls(异步运行队列)长度小于64且指向同一host的运行异步call小于5,
        //则取出异步call放入executableCalls和runningAsyncCalls(异步运行队列)中,
        //从readyAsyncCalls中移除该异步Call
        for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
            AsyncCall asyncCall = i.next();

            if (runningAsyncCalls.size() >= maxRequests) break; // Max capacity.
            if (runningCallsForHost(asyncCall) >= maxRequestsPerHost) continue; // Host max capacity.

            i.remove();
            executableCalls.add(asyncCall);
            runningAsyncCalls.add(asyncCall);
        }
        
        //如果不为空,说明还有需要执行的异步call
        isRunning = runningCallsCount() > 0;
    }

    //再一次循环,取出所有可以执行的异步call,放入线程池(executorService)中执行
    for (int i = 0, size = executableCalls.size(); i < size; i++) {
        AsyncCall asyncCall = executableCalls.get(i);
        asyncCall.executeOn(executorService());
    }

    return isRunning;
}
Dispatcher:
//这是一个没有核心线程,以及无限大非核心线程,超时时间为60秒的线程池
public synchronized ExecutorService executorService() {
  if (executorService == null) {
    executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
        new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher", false));
  }
  return executorService;
}

asyncCall的executeOn方法:

void executeOn(ExecutorService executorService) {
  assert (!Thread.holdsLock(client.dispatcher()));
  boolean success = false;
  try {
    //放入线程池执行
    executorService.execute(this);
    success = true;
  } catch (RejectedExecutionException e) {
    InterruptedIOException ioException = new InterruptedIOException("executor rejected");
    ioException.initCause(e);
    eventListener.callFailed(RealCall.this, ioException);
    responseCallback.onFailure(RealCall.this, ioException);
  } finally {
    if (!success) {
      //这边会移除call然后寻找下一个可执行的
      client.dispatcher().finished(this); // This call is no longer running!
    }
  }
}
Dispatcher:
//异步call执行的finish方法
void finished(AsyncCall call) {
   finished(runningAsyncCalls, call);
}

//同步call执行的finish方法
void finished(RealCall call) {
  finished(runningSyncCalls, call);
}

//从对应队列中移除该call,然后遍历异步等待队列
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();

//如果没有可运行的异步call且idleCallback不为空(idleCallback自己设置),执行idleCallback run方法
  if (!isRunning && idleCallback != null) {
    idleCallback.run();
  }
}

上面已经把异步同步请求以及结束的一些细节讲完了,接下来就是最重要的请求流程了。

RealCall:
Response getResponseWithInterceptorChain() throws IOException {
  // Build a full stack of interceptors.
  List<Interceptor> interceptors = new ArrayList<>();
  interceptors.addAll(client.interceptors());
  interceptors.add(retryAndFollowUpInterceptor);
  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, null, null, null, 0,
      originalRequest, this, eventListener, client.connectTimeoutMillis(),
      client.readTimeoutMillis(), client.writeTimeoutMillis());

  Response response = chain.proceed(originalRequest);
  if (retryAndFollowUpInterceptor.isCanceled()) {
    closeQuietly(response);
    throw new IOException("Canceled");
  }
  return response;
}

这里先将用户设置的应用拦截器全部加入,然后再加入其它拦截器,再最后一个拦截器之前再加入用户设置的网络拦截器,这样的话应用拦截器即使在发生重定向时也只会执行一次,而网络拦截器就会多次执行了。构建出RealInterceptorChain对象,执行了proceed方法,请求就正式开始了。

RealInterceptorChain:
public Response proceed(Request request, StreamAllocation streamAllocation, HttpCodec httpCodec,
    RealConnection connection) throws IOException {
  //index每次回来一次都会加1,如果大于等于拦截器,说明执行过多出错
  if (index >= interceptors.size()) throw new AssertionError();

  calls++;

  // If we already have a stream, confirm that the incoming request will use it.
  if (this.httpCodec != null && !this.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.httpCodec != null && calls > 1) {
    throw new IllegalStateException("network interceptor " + interceptors.get(index - 1)
        + " must call proceed() exactly once");
  }

  //每次使用chain.process(request)方法就会回来这里,然后创建新的RealInterceptorChain对象,同时
  //index会递增加1,这样每次都会获取到数组中下一个拦截器,然后执行拦截器的intercept方法,同时还会
  //将新构建的RealInterceptorChain传进去
  RealInterceptorChain next = new RealInterceptorChain(interceptors, streamAllocation, httpCodec,
      connection, index + 1, request, call, eventListener, connectTimeout, readTimeout,
      writeTimeout);
  Interceptor interceptor = interceptors.get(index);
  Response response = interceptor.intercept(next);

  // Confirm that the next interceptor made its required call to chain.proceed().
  if (httpCodec != null && index + 1 < interceptors.size() && next.calls != 1) {
    throw new IllegalStateException("network interceptor " + interceptor
        + " must call proceed() exactly once");
  }

  // Confirm that the intercepted response isn't null.
  if (response == null) {
    throw new NullPointerException("interceptor " + interceptor + " returned null");
  }

  if (response.body() == null) {
    throw new IllegalStateException(
        "interceptor " + interceptor + " returned a response with no body");
  }

  return response;
}

先看retryAndFollowUpInterceptor,这也是系统设置的第一个拦截器:

retryAndFollowUpInterceptor:
@Override public Response intercept(Chain chain) throws IOException {
  Request request = chain.request();
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  Call call = realChain.call();
  EventListener eventListener = realChain.eventListener();

  //用来管理connections、stream、routerSelector的类
  StreamAllocation streamAllocation = new StreamAllocation(client.connectionPool(),
      createAddress(request.url()), call, eventListener, callStackTrace);
  this.streamAllocation = streamAllocation;
  
  //重定向次数
  int followUpCount = 0;

  //如果发生重定向,记录上次的response
  Response priorResponse = null;

  //循环获取请求结果
  while (true) {
    //如果取消了,则释放流
    if (canceled) {
      streamAllocation.release();
      throw new IOException("Canceled");
    }

    Response response;
    boolean releaseConnection = true;
    try {
      //会回到realChainInterceptor的proceed方法,传递过去stremAllocation,
      //构建新realChain,执行下一个拦截器
      response = realChain.proceed(request, streamAllocation, null, null);
      releaseConnection = false;
    } catch (RouteException e) {
      // The attempt to connect via a route failed. The request will not have been sent.
      if (!recover(e.getLastConnectException(), streamAllocation, false, request)) {
        throw e.getFirstConnectException();
      }
      releaseConnection = false;
      continue;
    } catch (IOException e) {
      // An attempt to communicate with a server failed. The request may have been sent.
      boolean requestSendStarted = !(e instanceof ConnectionShutdownException);
      if (!recover(e, streamAllocation, requestSendStarted, request)) throw e;
      releaseConnection = false;
      continue;
    } finally {
      // We're throwing an unchecked exception. Release any resources.
      if (releaseConnection) {
        streamAllocation.streamFailed(null);
        streamAllocation.release();
      }
    }

    // Attach the prior response if it exists. Such responses never have a body.
    if (priorResponse != null) {
      response = response.newBuilder()
          .priorResponse(priorResponse.newBuilder()
                  .body(null)
                  .build())
          .build();
    }

    //这里是获取重定向请求
    Request followUp;
    try {
      //如果是407代理认证则执行client.proxyAuthenticator().authenticate(router,userResponse)方法
      //如果是401身份认证则执行client.authenticator().authenticate(route, userResponse)
      //OkHttpClient默认初始化为Authenticator.NONE
      //如果是其他一些3xx的则获取location网址,重新包装request请求等等,不支持则返回null
      followUp = followUpRequest(response, streamAllocation.route());
    } catch (IOException e) {
      streamAllocation.release();
      throw e;
    }

    //重定向请求不支持或不需要,释放流,返回response,请求结束
    if (followUp == null) {
      streamAllocation.release();
      return response;
    }

    closeQuietly(response.body());

    //如果重定向次数超过20,则释放流,并抛出异常
    if (++followUpCount > MAX_FOLLOW_UPS) {
      streamAllocation.release();
      throw new ProtocolException("Too many follow-up requests: " + followUpCount);
    }

    if (followUp.body() instanceof UnrepeatableRequestBody) {
      streamAllocation.release();
      throw new HttpRetryException("Cannot retry streamed HTTP body", response.code());
    }

     //判断重定向请求和前一个请求是否是同一个主机,如果不是重新创建连接
    if (!sameConnection(response, followUp.url())) {
      streamAllocation.release();
      streamAllocation = new StreamAllocation(client.connectionPool(),
          createAddress(followUp.url()), call, eventListener, callStackTrace);
      this.streamAllocation = streamAllocation;
    } else if (streamAllocation.codec() != null) {
      throw new IllegalStateException("Closing the body of " + response
          + " didn't close its backing stream. Bad interceptor?");
    }

    request = followUp;
    priorResponse = response;
  }
}

第二个拦截器,也是最简单的拦截器了,BridgeInterceptor:

BridgeInterceptor:
@Override public Response intercept(Chain chain) throws IOException {
  Request userRequest = chain.request();
  Request.Builder requestBuilder = userRequest.newBuilder();

  RequestBody body = userRequest.body();
  if (body != null) {
    //不为空,添加参数类型
    MediaType contentType = body.contentType();
    if (contentType != null) {
      requestBuilder.header("Content-Type", contentType.toString());
    }

    //能确定contentLendth,就移除Transfer-Encoding(代表不确定内容长度),否则反过来
    long contentLength = body.contentLength();
    if (contentLength != -1) {
      requestBuilder.header("Content-Length", Long.toString(contentLength));
      requestBuilder.removeHeader("Transfer-Encoding");
    } else {
      requestBuilder.header("Transfer-Encoding", "chunked");
      requestBuilder.removeHeader("Content-Length");
    }
  }

  //添加请求地址头
  if (userRequest.header("Host") == null) {
    requestBuilder.header("Host", hostHeader(userRequest.url(), false));
  }

  //http1.1开始默认开启Keep-Alive
  if (userRequest.header("Connection") == null) {
    requestBuilder.header("Connection", "Keep-Alive");
  }

  //如果没指定编码方式以及请求范围,则添加gzip方式
  boolean transparentGzip = false;
  if (userRequest.header("Accept-Encoding") == null && userRequest.header("Range") == null) {
    transparentGzip = true;
    requestBuilder.header("Accept-Encoding", "gzip");
  }
  
  //看是否有cookie信息,默认设置为OkHttpClient设置的NO_COOKIES
  List<Cookie> cookies = cookieJar.loadForRequest(userRequest.url());
  if (!cookies.isEmpty()) {
    requestBuilder.header("Cookie", cookieHeader(cookies));
  }

  //添加版本信息,这里默认写死的“okhttp/3.12.3”(跟okHttp版本相关)
  if (userRequest.header("User-Agent") == null) {
    requestBuilder.header("User-Agent", Version.userAgent());
  }

  //责任链继续执行下一个拦截器
  Response networkResponse = chain.proceed(requestBuilder.build());

  //保存cookie信息
  HttpHeaders.receiveHeaders(cookieJar, userRequest.url(), networkResponse.headers());

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

 //判断服务器是否支持gzip压缩,如果支持,则将压缩提交给Okio库来处理
  if (transparentGzip
      && "gzip".equalsIgnoreCase(networkResponse.header("Content-Encoding"))
      && 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)));
  }

  return responseBuilder.build();
}

下一个拦截器就是CacheIntercepter,听上去就知道是缓存拦截器了,这里的cache也是需要初始化OkHttpClient时候传入,默认为空,缓存策略详细可看这里blog.csdn.net/qq_30993595…

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

  long now = System.currentTimeMillis();

  //这边会去解析cacheCandidate(如果不为空)和request的请求头,获取请求缓存的规则
  CacheStrategy strategy = new CacheStrategy.Factory(now, chain.request(), cacheCandidate).get();
   //networkRequest为null则不用网络
  Request networkRequest = strategy.networkRequest;
  //cacheResponse为null则不用缓存
  Response cacheResponse = strategy.cacheResponse;

  //更新缓存策略
  if (cache != null) {
    cache.trackResponse(strategy);
  }

  //获取到本地缓存但是不用缓存,关闭缓存
  if (cacheCandidate != null && cacheResponse == null) {
    closeQuietly(cacheCandidate.body()); // The cache candidate wasn't applicable. Close it.
  }

  //不用网络也不用缓存,也就是本地无缓存且请求头有only-if-cached信息,返回504错误
  if (networkRequest == null && cacheResponse == null) {
    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 (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());
    }
  }

  //可以使用缓存且后台返回304,表明可以继续使用原先缓存,合并缓存和响应,更新缓存
  if (cacheResponse != null) {
    if (networkResponse.code() == HTTP_NOT_MODIFIED) {
      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) {
    //如果响应有响应体且返回码正常,请求头和响应头都无no-store值,则写入缓存并返回
    if (HttpHeaders.hasBody(response) && CacheStrategy.isCacheable(response, networkRequest)) {
      // Offer this request to the cache.
      CacheRequest cacheRequest = cache.put(response);
      return cacheWritingResponse(cacheRequest, response);
    }

    //移除非法缓存,例如post,put一类方法的
    if (HttpMethod.invalidatesCache(networkRequest.method())) {
      try {
        cache.remove(networkRequest);
      } catch (IOException ignored) {
        // The cache cannot be written.
      }
    }
  }

  return response;
}

接下来就是ConnectInterceptor拦截器,连接服务器,这里用到了在RetryAndFollowUpInterceptor拦截器中创建的StreamAllocation对象了:

ConnectInterceptor:
@Override public Response intercept(Chain chain) throws IOException {
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  Request request = realChain.request();
  StreamAllocation streamAllocation = realChain.streamAllocation();

  boolean doExtensiveHealthChecks = !request.method().equals("GET");
  //用来编码HTTP请求和解码HTTP响应
  HttpCodec httpCodec = streamAllocation.newStream(client, chain, doExtensiveHealthChecks);
  //里面保存了一个Socket负责连接,Handshake负责握手,
  //List<Reference< StreamAllocation>> allocations负责保存开辟的stream 
  RealConnection connection = streamAllocation.connection();

  return realChain.proceed(request, streamAllocation, httpCodec, connection);
}

代码如上,连接操作由streamAllocation来完成,接下来就是比较复杂的代码了:

StreamAllocation:
public HttpCodec newStream(
        OkHttpClient client, Interceptor.Chain chain, boolean doExtensiveHealthChecks) {
    //连接超时,默认10秒
    int connectTimeout = chain.connectTimeoutMillis();
    //读取超时,默认10秒
    int readTimeout = chain.readTimeoutMillis();
    //写入超时,默认10秒
    int writeTimeout = chain.writeTimeoutMillis();
    //Websocket ping 间隔 (毫秒) 定时通知服务器,为心跳连接做准备,默认为0,不执行心跳
    int pingIntervalMillis = client.pingIntervalMillis();
    //失败重连,默认true
    boolean connectionRetryEnabled = client.retryOnConnectionFailure();

    try {
        //寻找连接
        RealConnection resultConnection = findHealthyConnection(connectTimeout, readTimeout,
                writeTimeout, pingIntervalMillis, connectionRetryEnabled, doExtensiveHealthChecks);
        HttpCodec resultCodec = resultConnection.newCodec(client, chain, this);

        synchronized (connectionPool) {
            codec = resultCodec;
            return resultCodec;
        }
    } catch (IOException e) {
        throw new RouteException(e);
    }
}

private RealConnection findHealthyConnection(int connectTimeout, int readTimeout,
                                             int writeTimeout, int pingIntervalMillis, boolean connectionRetryEnabled,
                                             boolean doExtensiveHealthChecks) throws IOException {
    //循环寻找连接
    while (true) {
        RealConnection candidate = findConnection(connectTimeout, readTimeout, writeTimeout,
                pingIntervalMillis, connectionRetryEnabled);

        //新建的连接的successCount为0,直接返回
        synchronized (connectionPool) {
            if (candidate.successCount == 0) {
                return candidate;
            }
        }

        //如果被关闭了,则释放连接
        if (!candidate.isHealthy(doExtensiveHealthChecks)) {
            noNewStreams();
            continue;
        }

        return candidate;
    }
}

上面代码都知识来调用方法查找连接,查找连接的具体如下:

StreamAllocation:
private RealConnection findConnection(int connectTimeout, int readTimeout, int writeTimeout,
    int pingIntervalMillis, boolean connectionRetryEnabled) throws IOException {
  boolean foundPooledConnection = false;
  RealConnection result = null;
  Route selectedRoute = null;
  Connection releasedConnection;
  Socket toClose;
  synchronized (connectionPool) {
    //判断是否符合条件
    if (released) throw new IllegalStateException("released");
    if (codec != null) throw new IllegalStateException("codec != null");
    if (canceled) throw new IOException("Canceled");

    //如果有连接存在,直接复用
    releasedConnection = this.connection;

    //如果当前连接已经不能分配新的流,就释放资源,并返回当前连接的Socket对象,
    //并会把this.connection置为null
    toClose = releaseIfNoNewStreams();
    if (this.connection != null) {
      result = this.connection;
      releasedConnection = null;
    }
    if (!reportedAcquired) {
      // If the connection was never reported acquired, don't report it as released!
      releasedConnection = null;
    }

    if (result == null) {
      // 这个instance在OkHttpClient中实例化了.
      // 实际调用了ConnectionPool中的get(address,steamallocation,route)方法
      // 遍历存在的连接,符合条件的取出复用
      Internal.instance.get(connectionPool, address, this, null);
      if (connection != null) {
        foundPooledConnection = true;
        result = connection;
      } else {
        selectedRoute = route;
      }
    }
  }
  //关闭当前不能分配流的socket
  closeQuietly(toClose);

  if (releasedConnection != null) {
    eventListener.connectionReleased(call, releasedConnection);
  }
  if (foundPooledConnection) {
    eventListener.connectionAcquired(call, result);
  }
  if (result != null) {
    // If we found an already-allocated or pooled connection, we're done.
    route = connection.route();
    return result;
  }

  //上面没有从连接池里找到合适的连接,需要递归创建一个路由,是个阻塞的过程
  boolean newRouteSelection = false;
  if (selectedRoute == null && (routeSelection == null || !routeSelection.hasNext())) {
    newRouteSelection = true;
    routeSelection = routeSelector.next();
  }

  synchronized (connectionPool) {
    if (canceled) throw new IOException("Canceled");

    if (newRouteSelection) {
      // 现在有了ip address,那就更换路由再从连接池里获取 对多IP的支持
      List<Route> routes = routeSelection.getAll();
      for (int i = 0, size = routes.size(); i < size; i++) {
        Route route = routes.get(i);
        Internal.instance.get(connectionPool, address, this, route);
        if (connection != null) {
          foundPooledConnection = true;
          result = connection;
          this.route = route;
          break;
        }
      }
    }

    if (!foundPooledConnection) {
      if (selectedRoute == null) {
        selectedRoute = routeSelection.next();
      }

     // 到这里说明实在找不到 必须要实例化一个连接了
      route = selectedRoute;
      refusedStreamCount = 0;
      result = new RealConnection(connectionPool, selectedRoute);
      //表明要用这个连接
      acquire(result, false);
    }
  
// If we found a pooled connection on the 2nd time around, we're done.
if (foundPooledConnection) {
  eventListener.connectionAcquired(call, result);
  return result;
}

// 对于新创建的连接,要执行TCP + TLS握手来建立连接 阻塞操作(这里会创建socket)
result.connect(connectTimeout, readTimeout, writeTimeout, pingIntervalMillis,
    connectionRetryEnabled, call, eventListener);
//移除失败名单
routeDatabase().connected(result.route());

Socket socket = null;
synchronized (connectionPool) {
  reportedAcquired = true;

  //将连接放入连接池
  Internal.instance.put(connectionPool, result);

  // If another multiplexed connection to the same address was created concurrently, then
  // release this connection and acquire that one.
  if (result.isMultiplexed()) {
    // 如果当前创建的连接支持多路复用(只要是HTTP/2连接,就可以同时用于多个HTTP请求),
   //同时连接池里存在一个同样的连接,那就释放掉当前这个连接,复用连接池里的连接
    socket = Internal.instance.deduplicate(connectionPool, address, this);
    result = connection;
  }
}
closeQuietly(socket);

eventListener.connectionAcquired(call, result);
return result;

细节可参考:www.jianshu.com/p/6166d2898…

接下来来到最后一个拦截器,CallServerInterceptor,给服务器发送数据:

CallServerInterceptor:
@Override public Response intercept(Chain chain) throws IOException {
  //拿到之前初始好的对象
  RealInterceptorChain realChain = (RealInterceptorChain) chain;
  HttpCodec httpCodec = realChain.httpStream();
  StreamAllocation streamAllocation = realChain.streamAllocation();
  RealConnection connection = (RealConnection) realChain.connection();
  Request request = realChain.request();

  //记录发送时间
  long sentRequestMillis = System.currentTimeMillis();

  realChain.eventListener().requestHeadersStart(realChain.call());
  //往sink里写入请求头
  httpCodec.writeRequestHeaders(request);
  realChain.eventListener().requestHeadersEnd(realChain.call(), request);

  Response.Builder responseBuilder = null;
  //如果不是get请求,也就是有请求体
  if (HttpMethod.permitsRequestBody(request.method()) && request.body() != null) {
     //如果请求头中有"Expect: 100-continue"协议,等待服务器返回100确定是否接收请求体
    // If there's a "Expect: 100-continue" header on the request, wait for a "HTTP/1.1 100
    // Continue" response before transmitting the request body. If we don't get that, return
    // what we did get (such as a 4xx response) without ever transmitting the request body.
    if ("100-continue".equalsIgnoreCase(request.header("Expect"))) {
      httpCodec.flushRequest();
      realChain.eventListener().responseHeadersStart(realChain.call());
      responseBuilder = httpCodec.readResponseHeaders(true);
    }

    //如果服务器返回100,那responseBuilder为null,说明服务器等待接收请求体,开始写入请求体
    if (responseBuilder == null) {
      // Write the request body if the "Expect: 100-continue" expectation was met.
      realChain.eventListener().requestBodyStart(realChain.call());
      long contentLength = request.body().contentLength();
      CountingSink requestBodyOut =
          new CountingSink(httpCodec.createRequestBody(request, contentLength));
      BufferedSink bufferedRequestBody = Okio.buffer(requestBodyOut);

      request.body().writeTo(bufferedRequestBody);
      bufferedRequestBody.close();
      realChain.eventListener()
          .requestBodyEnd(realChain.call(), requestBodyOut.successfulCount);
    } else if (!connection.isMultiplexed()) {
      // If the "Expect: 100-continue" expectation wasn't met, prevent the HTTP/1 connection
      // from being reused. Otherwise we're still obligated to transmit the request body to
      // leave the connection in a consistent state.
      streamAllocation.noNewStreams();
    }
  }
  //sink.flush()
  httpCodec.finishRequest();

  //读取响应头
  if (responseBuilder == null) {
    realChain.eventListener().responseHeadersStart(realChain.call());
    responseBuilder = httpCodec.readResponseHeaders(false);
  }

  Response response = responseBuilder
      .request(request)
      .handshake(streamAllocation.connection().handshake())
      .sentRequestAtMillis(sentRequestMillis)
      .receivedResponseAtMillis(System.currentTimeMillis())
      .build();

  //读取响应体
  int code = response.code();
  if (code == 100) {
    // server sent a 100-continue even though we did not request one.
    // try again to read the actual response
    responseBuilder = httpCodec.readResponseHeaders(false);

    response = responseBuilder
            .request(request)
            .handshake(streamAllocation.connection().handshake())
            .sentRequestAtMillis(sentRequestMillis)
            .receivedResponseAtMillis(System.currentTimeMillis())
            .build();

    code = response.code();
  }

  realChain.eventListener()
          .responseHeadersEnd(realChain.call(), response);

  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()
        .body(httpCodec.openResponseBody(response))
        .build();
  }

  if ("close".equalsIgnoreCase(response.request().header("Connection"))
      || "close".equalsIgnoreCase(response.header("Connection"))) {
    streamAllocation.noNewStreams();
  }

  if ((code == 204 || code == 205) && response.body().contentLength() > 0) {
    throw new ProtocolException(
        "HTTP " + code + " had non-zero Content-Length: " + response.body().contentLength());
  }

  return response;
}

到这里整个请求就结束了,核心类是 RealConnection、ConnectionPool、StreamAllocation

最后是这两张图(别人博客拿的)