`
daojin
  • 浏览: 677348 次
  • 性别: Icon_minigender_1
  • 来自: 西安
社区版块
存档分类
最新评论

OKHttp3.14.5源代码解析

阅读更多
Rxjava:
https://www.jianshu.com/p/7474950af2df

基本使用方式
创建Request

Request request = new Request.Builder().url().get().build(); 


创建OkHttpClient
OkHttpClient client = new OkHttpClient(); 
 
public final OkHttpClient client = new OkHttpClient.Builder() 
        .addInterceptor(new HttpLoggingInterceptor()) 
        .cache(new Cache(cacheDir, cacheSize)) 
        .build(); 
 
 
   OkHttpClient client = client.newBuilder() 
        .readTimeout(500, TimeUnit.MILLISECONDS) 
       .build(); 


执行
 Response response = client.newCall(request).execute();

client.newCall(request).enqueue(callback);


清理

client.dispatcher().executorService().shutdown();
client.connectionPool().evictAll();
 client.cache().close();


代码流程分析
创建RealCall
  private RealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    this.client = client;
    this.originalRequest = originalRequest;
    this.forWebSocket = forWebSocket;
  }

  static RealCall newRealCall(OkHttpClient client, Request originalRequest, boolean forWebSocket) {
    // Safely publish the Call instance to the EventListener.

如果是同步的call
直接调用RealCall.execute

 private int maxRequests = 64;			
		  private int maxRequestsPerHost = 5;			
					
  @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);					
    }					
  }

如若调用enqueue方法,就会走到AsyncCall
  @Override public void enqueue(Callback responseCallback) {					
    synchronized (this) {					
      if (executed) throw new IllegalStateException("Already Executed");					
      executed = true;					
    }					
    transmitter.callStart();					
    client.dispatcher().enqueue(new AsyncCall(responseCallback));					
  }					
	

AsyncCall是Runnalbe 包装了callback

client.dispatcher().enqueue调用了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; // Max capacity.					
        if (asyncCall.callsPerHost().get() >= maxRequestsPerHost) continue; // Host max capacity.					
					
        i.remove();					
        asyncCall.callsPerHost().incrementAndGet();					
        executableCalls.add(asyncCall);					
        runningAsyncCalls.add(asyncCall);					
      }					
      isRunning = runningCallsCount() > 0;					
    }					
					
    for (int i = 0, size = executableCalls.size(); i < size; i++) {					
      AsyncCall asyncCall = executableCalls.get(i);					
      asyncCall.executeOn(executorService());					
    }					
					
    return isRunning;					
  }					
					
					
 asyncCall.executeOn(executorService());					
					

					
    /**					
     * Attempt to enqueue this async call on {@code executorService}. This will attempt to clean up					
     * if the executor has been shut down by reporting the call as failed.					
     */					
    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);					
        transmitter.noMoreExchanges(ioException);					
        responseCallback.onFailure(RealCall.this, ioException);					
      } finally {					
        if (!success) {					
          client.dispatcher().finished(this); // This call is no longer running!					
        }					
      }					
    }	

下面执行到了execute,调用 Response response = getResponseWithInterceptorChain();

 
   @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);					
        }					
      } catch (Throwable t) {					
        cancel();					
        if (!signalledCallback) {					
          IOException canceledException = new IOException("canceled due to " + t);					
          canceledException.addSuppressed(t);					
          responseCallback.onFailure(RealCall.this, canceledException);					
        }					
        throw t;					
      } finally {					
        client.dispatcher().finished(this);					
      }					
    }					
					
getResponseWithInterceptorChain() 					
  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);					
      if (transmitter.isCanceled()) {					
        closeQuietly(response);					
        throw new IOException("Canceled");					
      }					
      return response;					
    } catch (IOException e) {					
      calledNoMoreExchanges = true;					
      throw transmitter.noMoreExchanges(e);					
    } finally {					
      if (!calledNoMoreExchanges) {					
        transmitter.noMoreExchanges(null);					
      }					
    }					
  }					
RealInterceptorChain.proceed					
					
					
  public Response proceed(Request request, Transmitter transmitter, @Nullable Exchange exchange)					
      throws IOException {					
					
					
 Response response = interceptor.intercept(next);					
					
}	


接下来走到Interceptor.intercept
RealCall.getResponseWithInterceptorChain 可以看到有四个					
    interceptors.add(new RetryAndFollowUpInterceptor(client));					
    interceptors.add(new BridgeInterceptor(client.cookieJar()));					
    interceptors.add(new CacheInterceptor(client.internalCache()));					
    interceptors.add(new ConnectInterceptor(client));					
CallServerInterceptor	



RetryAndFollowUpInterceptor 处理3XX重定向的,4XX授权,5xx服务器错误retry等

Location
  @Override public Response intercept(Chain chain)
Request followUp = followUpRequest(response, route);
 case HTTP_MULT_CHOICE:
      case HTTP_MOVED_PERM:
      case HTTP_MOVED_TEMP:
      case HTTP_SEE_OTHER:
        // Does the client allow redirects?
        if (!client.followRedirects()) return null;

        String location = userResponse.header("Location");


BridgeInterceptor
添加了很多header,并且加入了gzip

CacheInterceptor 处理cache
ConnectInterceptor 创建Exechange,建立连接
CallServerInterceptor 调用

exchange.writeRequestHeaders(request);					
					
  if (responseBuilder == null) {					
      responseBuilder = exchange.readResponseHeaders(false);					
    }					
					
    Response response = responseBuilder					
        .request(request)					
        .handshake(exchange.connection().handshake())					
        .sentRequestAtMillis(sentRequestMillis)					
        .receivedResponseAtMillis(System.currentTimeMillis())					
        .build();					
			



题外话:
ConnectionPool
最大5个链接,最长 5分钟
实现是RealConnectionPool

Http1.0 很明显无法复用socket链接。

Http2.0 可以复用socket链接







分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics