okhttp同步、异步请求分发分析。

使用okhttp的第一步就是初始化了一个连接池,但是这个连接池是嵌套在Internal这个抽象类里面,为什么是使用抽象类,这个我需要思考一下。其中如何对线程池get和put,这个后续会分析到。

public class OkHttpClient implements Cloneable, Call.Factory, WebSocket.Factory {
    static {
        Internal.instance = new Internal() {
            @Override
            public void addLenient(Headers.Builder builder, String line) {
                builder.addLenient(line);
            }

            @Override
            public void addLenient(Headers.Builder builder, String name, String value) {
                builder.addLenient(name, value);
            }

            @Override
            public void setCache(Builder builder, InternalCache internalCache) {
                builder.setInternalCache(internalCache);
            }

            @Override
            public boolean connectionBecameIdle(
                    ConnectionPool pool, RealConnection connection) {
                return pool.connectionBecameIdle(connection);
            }

            @Override
            public RealConnection get(ConnectionPool pool, Address address,
                                      StreamAllocation streamAllocation, Route route) {
                return pool.get(address, streamAllocation, route);
            }

            @Override
            public boolean equalsNonHost(Address a, Address b) {
                return a.equalsNonHost(b);
            }

            @Override
            public Socket deduplicate(
                    ConnectionPool pool, Address address, StreamAllocation streamAllocation) {
                return pool.deduplicate(address, streamAllocation);
            }

            @Override
            public void put(ConnectionPool pool, RealConnection connection) {
                pool.put(connection);
            }

            @Override
            public RouteDatabase routeDatabase(ConnectionPool connectionPool) {
                return connectionPool.routeDatabase;
            }

            @Override
            public int code(Response.Builder responseBuilder) {
                return responseBuilder.code;
            }

            @Override
            public void apply(ConnectionSpec tlsConfiguration, SSLSocket sslSocket,
                              boolean isFallback) {
                tlsConfiguration.apply(sslSocket, isFallback);
            }

            @Override
            public HttpUrl getHttpUrlChecked(String url)
                    throws MalformedURLException, UnknownHostException {
                return HttpUrl.getChecked(url);
            }

            @Override
            public StreamAllocation streamAllocation(Call call) {
                return ((RealCall) call).streamAllocation();
            }

            @Override
            public Call newWebSocketCall(OkHttpClient client, Request originalRequest) {
                return RealCall.newRealCall(client, originalRequest, true);
            }
        };
    }
}

不管是异步请求也好还是同步请求都会通过dispatcher的线程池进行分发。

final class RealCall implements Call {

   @Override
    public Response execute() throws IOException {
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        try {
            client.dispatcher().executed(this);
            // 发起请求
            Response result = getResponseWithInterceptorChain();
            if (result == null) throw new IOException("Canceled");
            return result;
        } catch (IOException e) {
            eventListener.callFailed(this, e);
            throw e;
        } finally {
            client.dispatcher().finished(this);
        }
    }
    
  @Override
    public void enqueue(Callback responseCallback) {
        synchronized (this) {
            if (executed) throw new IllegalStateException("Already Executed");
            executed = true;
        }
        captureCallStackTrace();
        eventListener.callStart(this);
        //将一个requeset请求包装成一个realcall,放入一部请求中
        client.dispatcher().enqueue(new AsyncCall(responseCallback));
    }
    final class AsyncCall extends NamedRunnable {
        @Override
        protected void execute() {
            boolean signalledCallback = false;
            try {
                //执行请求 (拦截器)
                Response response = getResponseWithInterceptorChain();

                if (retryAndFollowUpInterceptor.isCanceled()) {
                    signalledCallback = true;
                    responseCallback.onFailure(RealCall.this, new IOException("Canceled"));
                } else {
                    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 {
                    eventListener.callFailed(RealCall.this, e);
                    responseCallback.onFailure(RealCall.this, e);
                }
            } finally {
                client.dispatcher().finished(this);
            }
        }
    //进入责任链模式,开始经行网络请求
    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) {
             //针对websocket的网络连接器
            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());

        return chain.proceed(originalRequest);
    }
}

其中dispatcher的任务是当任务开始执行时将任务插入队列中,当任务结束时将任务remove掉。dispatcher有3个队列,同步/异步 队列,其中一个是ready队列。

public final class Dispatcher {
    private int maxRequests = 64;
    private int maxRequestsPerHost = 5;
     /**
     * 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<>();

    /**
     * Running synchronous calls. Includes canceled calls that haven't finished yet.
     */
    private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();
    
    public synchronized ExecutorService executorService() {
        if (executorService == null) {
            //核心线程数为0,则无需等待直接执行该线程。Integer.MAX_VALUE保证了线程的最大并发量
            //60s为线程最大等待时间,SynchronousQueue不存储如何线程,如果有就立即执行。
            executorService = new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60, TimeUnit.SECONDS,
                    new SynchronousQueue<Runnable>(), Util.threadFactory("OkHttp Dispatcher",
                    false));
        }
        return executorService;
    }
    
    synchronized void executed(RealCall call) {
        runningSyncCalls.add(call);
    }
    
    synchronized void enqueue(AsyncCall call) {
        //todo : 1、如果正在执行的请求小于64
        // 2、相同host的请求不能超过5个
        if (runningAsyncCalls.size() < maxRequests && runningCallsForHost(call) < maxRequestsPerHost) {
            runningAsyncCalls.add(call);  //正在执行的请求
            executorService().execute(call); //线程池跑任务
        } else {
            //加入ready队列
            readyAsyncCalls.add(call);
        }
    }
    
 //异步请求
 void finished(AsyncCall call) {
        finished(runningAsyncCalls, call, true);
    }

    //同步请求
    void finished(RealCall call) {
        finished(runningSyncCalls, call, false);
    }
    
    //promoteCalls判断是否为同步请求
    private <T> void finished(Deque<T> calls, T call, boolean promoteCalls) {
        int runningCallsCount;
        Runnable idleCallback;
        synchronized (this) {
            //在dispatcher列表中移除该请求
            if (!calls.remove(call)) throw new AssertionError("Call wasn't in-flight!");
            if (promoteCalls) promoteCalls();
            //总的请求数异步队列+同步队列就是最大请求数
            runningCallsCount = runningCallsCount();
            idleCallback = this.idleCallback;
        }

        if (runningCallsCount == 0 && idleCallback != null) {
            idleCallback.run();
        }
    }
     
     /**
     * 从ready获取任务放入异步队列执行
     */
    private void promoteCalls() {
        if (runningAsyncCalls.size() >= maxRequests) return; // Already running max capacity.
        if (readyAsyncCalls.isEmpty()) return; // No ready calls to promote.

        for (Iterator<AsyncCall> i = readyAsyncCalls.iterator(); i.hasNext(); ) {
            AsyncCall call = i.next();
            // 同一Host请求只能同时有5个
            if (runningCallsForHost(call) < maxRequestsPerHost) {
                i.remove();
                runningAsyncCalls.add(call);
                executorService().execute(call);
            }

            if (runningAsyncCalls.size() >= maxRequests) return; // Reached max capacity.
        }
    }
 }

总结:okhttpclient初始化连接池为后续的连接做准备,realcall控制request请求执行的详细流程,而dispatcher管理同步和异步队列,以及ready队列。保证当一个异步请求完成时及时清理。并添加新的请求进行处理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值