OkHttp的执行流程

122 阅读2分钟
OkHttp中,异步请求的调用步骤一般如下:
```
val okHttpClient = OkHttpClient.Builder().build()
val request = Request.Builder()
    .url("https://www.baidu.com/").build()
val call = okHttpClient.newCall(request)
call.enqueue(object : Callback{
    override fun onFailure(call: Call, e: IOException) {
        println(e.message)
    }

    override fun onResponse(call: Call, response: Response) {
        println(response.body)
    }
})
```

RealCall

```
override fun newCall(request: Request): Call = RealCall(this, request, forWebSocket = false)
```
newCall(request)方法生成一个RealCall对象,RealCall实现了Call接口,call可以理解成准备好执行的请求,一个Call只能执行一次,它提供了请求相关的方法如同步请求execute()、异步请求enqueue(responseCallback)、取消请求cancel()、以及获取请求的状态isExecuted()、isCanceled()等。

Dispatcher

```
//RealCall
override fun enqueue(responseCallback: Callback) {
  check(executed.compareAndSet(false, true)) { "Already Executed" }

  callStart()
  client.dispatcher.enqueue(AsyncCall(responseCallback))
}
//Dispatcher
internal fun enqueue(call: AsyncCall) {
  synchronized(this) {
    readyAsyncCalls.add(call)
    if (!call.call.forWebSocket) {
      val existingCall = findExistingCallWithHost(call.host)
      if (existingCall != null) call.reuseCallsPerHostFrom(existingCall)
    }
  }
  promoteAndExecute()
}
```
RealCall的enqueue方法调用了Dispatcher的enqueue方法,并传递了AsyncCall,AsyncCall是RealCall的内部类。
对于异步请求,Dispatcher提供了两个队列readyAsyncCalls和runningAsyncCalls,分别存储准备好的Call和正在执行的Call,在enqueue方法中首先就是把AsyncCall放入readyAsyncCalls中。
AsyncCall中有一个属性callsPerHost,表示当前连接host的数量,如果call要请求的host相同,它们的callsPerHost值是共享的,具体实现就在findExistingCallWithHost和call.reuseCallsPerHostFrom(existingCall)处,逻辑就是在readyAsyncCalls和runningAsyncCalls中寻找和当前call的host一致的其他call,把其他call的callsPerHost赋值给当前call。
```
private fun promoteAndExecute(): Boolean {
  this.assertThreadDoesntHoldLock()

  val executableCalls = mutableListOf<AsyncCall>()
  val isRunning: Boolean
  synchronized(this) {
    val i = readyAsyncCalls.iterator()
    while (i.hasNext()) {
      val asyncCall = i.next()

  if (runningAsyncCalls.size >= this.maxRequests) break 
  if (asyncCall.callsPerHost.get() >= this.maxRequestsPerHost) continue capacity.

  i.remove()
  asyncCall.callsPerHost.incrementAndGet()
  executableCalls.add(asyncCall)
  runningAsyncCalls.add(asyncCall)
}
    isRunning = runningCallsCount() > 0
  }

  for (i in 0 until executableCalls.size) {
    val asyncCall = executableCalls[i]
    asyncCall.executeOn(executorService)
  }
  return isRunning
}
```
promoteAndExecute()方法中,当readyAsyncCalls中有数据时,需要做两个判断:1.runningAsyncCalls(当前正在执行的请求)需要小于maxRequests(64);2.单个host同一时刻的请求数量最多不能超过maxRequestsPerHost(5)。这两项满足后,将AsyncCall从readyAsyncCalls中取出放入runningAsyncCalls,同时使用线程池执行asyncCall,AsyncCall实现了Runnable接口。
```
@get:JvmName("executorService") val executorService: ExecutorService
  get() {
    if (executorServiceOrNull == null) {
      executorServiceOrNull = ThreadPoolExecutor(0, Int.MAX_VALUE, 60, TimeUnit.SECONDS,
          SynchronousQueue(), threadFactory("$okHttpName Dispatcher", false))
    }
    return executorServiceOrNull!!
  }
```
executorService的核心线程数是0,最大线程数无限制,说明只要有请求过来就会创建线程立即执行,不会等待。由于前面有runningAsyncCalls<=64的限制,这里创建的线程数量也是有限的。

AsyncCall

   override fun run() {
       threadName("OkHttp ${redactedUrl()}") {
         var signalledCallback = false
         timeout.enter()
         try {
           val response = getResponseWithInterceptorChain()
           signalledCallback = true
           responseCallback.onResponse(this@RealCall, response)
         } catch (e: IOException) {
           if (signalledCallback) {
             // Do not signal the callback twice!
             Platform.get().log("Callback failure for ${toLoggableString()}", Platform.INFO, e)
           } else {
             responseCallback.onFailure(this@RealCall, e)
           }
         } catch (t: Throwable) {
           cancel()
           if (!signalledCallback) {
             val canceledException = IOException("canceled due to $t")
             canceledException.addSuppressed(t)
             responseCallback.onFailure(this@RealCall, canceledException)
           }
           throw t
         } finally {
           client.dispatcher.finished(this)
         }
       }
     }
   }
AsyncCall的run方法核心就是getResponseWithInterceptorChain(),这里使用责任链模式,通过多个拦截器处理request,结果通过responseCallback传递给调用者。