当前位置: 首页 > wzjs >正文

asp网站 访问 变慢 监测合肥建设官方网站

asp网站 访问 变慢 监测,合肥建设官方网站,品牌整合营销,做的网站在不同浏览器我们先回顾一下OkHttp请求流程的一个通俗易懂的故事版本: 1. 挂号处(Dispatcher) 你(Request):来到医院说要体检(比如「全身检查」)。护士姐姐(Call)&#xf…

我们先回顾一下OkHttp请求流程的一个通俗易懂的故事版本:

1. 挂号处(Dispatcher)

  • 你(Request):来到医院说要体检(比如「全身检查」)。
  • 护士姐姐(Call):带你到挂号处分诊。
  • 挂号处(Dispatcher)
    • 如果当前体检科人不多(runningAsyncCalls < 64),直接给你排号(加入 runningAsyncCalls)。
    • 如果人满了(比如流感季),让你去等候区坐着(readyAsyncCalls队列)。

💡 关键:挂号处控制整体人流,防止体检科被挤爆(并发限制)。


2. 体检科线程池(Thread Pool)

  • 护士姐姐:从挂号处拿到你的号后,不亲自带你体检,而是交给体检科的空闲医生(线程池中的线程)。
  • 医生(线程):按照体检流程单(Interceptor Chain)一步步带你检查。

🌟 为什么需要医生?
护士姐姐如果亲自带你体检,她就没法服务其他人了(阻塞调用线程)。医生是专门干这事的(后台线程)。


3. 体检流程单(责任链 Interceptor Chain)

医生拿着流程单,带你去不同科室:

  1. 预检分诊台(RetryAndFollowUpInterceptor)

    • 先问你是否过敏(检查请求是否可重试)。
    • 如果血常规人太多(超时),带你去其他楼层重试(自动重试)。
  2. 登记处(BridgeInterceptor)

    • 帮你填表、补全个人信息(补全请求头:Content-TypeCookie)。
  3. 档案室(CacheInterceptor)

    • 检查你去年体检过没,如果项目相同且没过期,直接复印一份给你(返回缓存响应)。
  4. 抽血处(ConnectInterceptor)

    • 找护士长(连接池)问有没有一次性针管(Socket 连接),有就直接用(连接复用),没有就拿一个新的。
  5. X光室(CallServerInterceptor)

    • 终于真正做检查了(发送请求到服务器,接收响应)。

4. 体检报告(Response)

  • 医生:拿到所有科室结果后,整理成报告(Response),交还给护士姐姐
  • 护士姐姐
    • 如果体检成功,打电话通知你(onResponse)。
    • 如果中途医院停电了(IOException),告诉你改天再来(onFailure)。

5. 突发情况(取消与重试)

  • 你不想体检了(call.cancel())
    护士姐姐立刻广播通知所有科室停止检查(中断请求)。
  • 某项检查失败但可重试
    预检分诊台(RetryAndFollowUpInterceptor)会带你重新排队(自动重试),但最多重试 20 次(避免无限循环)。
  • 需要特殊重试
    比如体检要求空腹,但你吃了早饭,护士姐姐会记下需求(自定义拦截器),明天再来(手动重试)。

在了解OkHttp通俗易懂的故事之后,现在我们可以尝试写出源码大致版本,去更好的理解OkHttp整个架构,下面我们回顾它的基本使用,以GET请求为例:

String url = "https://www.baidu.com/";OkHttpClient client = new OkHttpClient();
// 配置GET请求
Request request = new Request.Builder().url(url).get().build();Call call = okHttpClient.newCall(request);
call.enqueue(new Callback() {@Overridepublic void onFailure(Call call, Throwable throwable) {}@Overridepublic void onResponse(Call call, Response response) {}
});

下面我们将自顶向下的一步一步写出大概的源码,不难看出我们需要新建OkHttpClient 、Request 、Call 以及Callback这些基本的类,而且Request 还用到了构建者设计模式,它的好处是可以像链式调用一下,在代码中其实就是方法体中执行完相关逻辑之后返回类本身就能够实现;首先我们先实现Request :

public class Request {// 作为一个请求,需要有以下功能// 请求方法,是 get 还是 postprivate String method = "GET";// 请求到哪里去,url地址;// HttpUrl通过url解析服务器主机名以及端口号之类的功能private HttpUrl httpUrl = null;// ...省略部分代码public static class Builder {public Builder url(String url) {return this;}public Builder get() {return this;}public Request build() {return new Request();}}
}

接着是实现Call,前面我们知道,Call将全程参与请求完整流程,则Call肯定是持有Request对象,然后enqueue方法会有一个callback作为参数:

public class Call {Request request;public Call(Request request) {this.request = request;}public Call enqueue(Callback callback) {return this;}
}

接着是OkHttpClient,从使用方式来看,我们一定知道里面有一个newCall方法,执行完成之后会返回Call对象:

public class OkHttpClient {public Call newCall(Request request) {return new Call(this, request);}
}

以及Callback接口,可以发现不论是成功还是失败,call对象都是全程参与,作用是支持开发者能够对网络请求的完全控制能力,比如可以在响应之后随时取消请求:

public interface Callback {void onFailure(Call call, Throwable throwable);void onResponse(Call call, Response response);
}

至此我们看到的方法大致已经实现完了,现在我们根据已知的信息把okhttp黑盒部分的源码实现。我们都知道:call带着request前往分发器dispatcher,分发器需要看情况这个请求要到哪个队列,比如当正在请求的队列满了就需要去等待队列,不难得出我们需要写出一个Dispatcher,并且至少维护着两个队列,且这两个队列是非阻塞队列;由于请求是耗时任务,不能直接执行(卡主线程),需要利用线程池特性去帮我们完成请求流程,所以会用到ExecutorService ,另外也维护着两个大家都知道的成员变量maxRequests和maxRequestPreHost:

public class Dispatcher {// 请求来了不一定能够执行,所以需要分发器;// Dispatcher 不能是 Call持有,不然护士姐姐的权利就是最大了,分分钟排到最前面// 异步请求下,分发器的分发方法,会涉及到两个队列,一个是正在请求的队列,另一个是等待队列// 现在我们知道队列里放的是请求,但能不能直接放 request进去呢?// 因为 request只记录的请求信息,至于要怎么做,并不是在 request里面定义。// 另外请求动作是一个耗时任务,所以这个请求动作是实现了 runnable的// 可以思考一下为什么不用阻塞队列private final Deque<Call.AsyncCall> runningAsyncCalls = new ArrayDeque<>();private final Deque<Call.AsyncCall> readyAsyncCalls = new ArrayDeque<>();// 分发器一共维护着3个队列,前面2个是异步的队列,剩下这个是同步队列,也需要被记录着// 当请求是同步的时候会被分发器加入到这里// private final Deque<RealCall> runningSyncCalls = new ArrayDeque<>();// 最多同时请求的数量private int maxRequests;// 同一个 host主机最多允许请求的数量private int maxRequestPreHost;private ExecutorService mExecutorService;public Dispatcher() {maxRequests = 64;maxRequestPreHost = 5;ThreadFactory threadFactory = new ThreadFactory() {@Overridepublic Thread newThread(Runnable r) {Thread httpClientThread = new Thread(r, "http client thread");return httpClientThread;}};// okhttp是没有常驻线程的mExecutorService = new ThreadPoolExecutor(0,Integer.MAX_VALUE, 60L, TimeUnit.SECONDS,new ArrayBlockingQueue<>(1), threadFactory);}// 分发器需要拿到 request,分发到具体的队列,然后 Call.AsyncCall真正的执行public void enqueue(Call.AsyncCall asyncCall) {// 判断放在哪个队列if (runningAsyncCalls.size() < maxRequests) {runningAsyncCalls.add(asyncCall);// 添加到队列之后,并不能执行。还需要线程池mExecutorService.submit(asyncCall);} else {// 所以等待队列理论上大小是无限的readyAsyncCalls.add(asyncCall);}}
}

然而现在我们知道队列里放的是请求,但能不能直接放request进去呢?很显然不能,因为 request只记录的请求信息,至于要怎么做,并不是在 request里面定义。另外请求动作是一个耗时任务,所以这个请求动作是实现了 runnable的,故我们还要在Call方法里面定义一个内部类并实现runnable;
前面有提到分发器不能是call持有,因为call作为护士姐姐小角色,不能越级去干超出她能力范围的事情,而是应该交给更大能力的,这里很显然是OkHttpClient 去持有:

public class Call {// ...省略部分代码private OkHttpClient mOkHttpClient;public Call enqueue(Callback callback) {synchronized (this) {if (executed) {throw new IllegalStateException("Already Executed!");}executed = true;}// Call 给到分发器mOkHttpClient.getDispatcher().enqueue(new AsyncCall(callback));return this;}final class AsyncCall implements Runnable {private Callback mCallback;public AsyncCall(Callback callback) {mCallback = callback;}@Overridepublic void run() {// 到了这里还不能直接执行请求,开始涉及到拦截器// 设计责任链模式,首先要创建一个接口// 为了能在一环又一环的链条上传递数据,还需要一个指挥者// 怎么组装责任链try {Response response = getResponse();// 因为是异步,所以通过接口返回mCallback.onResponse(Call.this, response);} catch (IOException e) {mCallback.onFailure(Call.this, e);}}}
}

回顾整个请求流程步骤,线程池分配线程去执行Call里面的请求任务AsyncCall ,接下来就是去组装责任链,并启动责任链程序。
关于责任链这里,我们都知道okhttp设计各种拦截器的主要原因,一个是为了把重试、请求头、获取长链接以及真正请求的逻辑去做一个解耦,另一个原因也是为了让开发者可以自定义增加或者删除拦截器。
这里我们简单实现一下okhttp的责任链,首先责任链会涉及到一个指挥者,我们需要定义一个接口,并定义一个拦截的方法intercept:

public interface Interceptor {Response intercept(InterceptorChain interceptorChain) throws IOException;
}

接着是指挥者的实现,为了能够让指挥者能够每次都执行下一个责任链,这里记录了list和index下标,当每次执行完一个环节都会自增,这里直接呼应了okhttp源代码:

public class InterceptorChain {// 指挥者需要持有这些环节private List<Interceptor> mInterceptors;// 记录执行到哪一个环private int index;private Call mCall;// 怎么组装责任链public InterceptorChain(List<Interceptor> list, int index, Call call) {mInterceptors = list;this.index = index;mCall = call;}public Response proceed() throws IOException {if (index > mInterceptors.size()) {// 判断是否超出throw new IOException("error");}// 获取当前执行的责任链// 最关键的地方,这个方法需要实现,当对应的责任链执行完之后要执行下一个责任链// 也就是每个责任链通过参数里面的指挥者,再次调用它自身的 proceed()方法InterceptorChain next = new InterceptorChain(mInterceptors, index + 1, mCall);Interceptor interceptor = mInterceptors.get(index);Response intercept = interceptor.intercept(next);return intercept;}
}

最后是各个责任链的实现,可以看到,当每个责任链都做完自己的事情后,通过chain参数再次调用proceed()方法就能执行下一个责任链的逻辑:

public class RetryInterceptor implements Interceptor {// 重试责任链@Overridepublic Response intercept(InterceptorChain interceptorChain) throws IOException {// ...省略部分代码Response proceed = interceptorChain.proceed();return proceed;}
}public class HeadersInterceptor implements Interceptor {// 请求头责任链public Response intercept(InterceptorChain interceptorChain) throws IOException {// ...省略部分代码Response proceed = interceptorChain.proceed();return proceed;}
}public class ConnectionInterceptor implements Interceptor {// 获取长链接责任链@Overridepublic Response intercept(InterceptorChain interceptorChain) throws IOException {// ...省略部分代码Response proceed = interceptorChain.proceed();return proceed;}
}public class CallServiceInterceptor implements Interceptor {// 请求处理责任链条@Overridepublic Response intercept(InterceptorChain interceptorChain) throws IOException {// ...省略部分代码Response proceed = interceptorChain.proceed();return proceed;}
}
http://www.dtcms.com/wzjs/582861.html

相关文章:

  • 模板网站官网潍坊网站建设seo
  • 福建厦门网站建设公司深圳网站设计 工作室
  • 网站提示宏简述网站建设的基本思路
  • 济南网站建设服务商重庆工商学校官网
  • 专业模板建站服务百度收录情况查询
  • 公司网站别人做的怎么签合同网站建设与网页制作案例
  • 马鞍山网站建设 明达建设信用卡激活中心网站
  • 企业产品网站模板南通小程序制作
  • 网站大全浏览器网站做用户登录
  • 网站建设方案书 百度文库沈阳网站建设服务
  • 工信部网站备案号不同类型网站优势
  • 网站功能项目报价画图在什么网站上做兼职
  • 不同类型网站比较及网站域名设计网站做广告费用
  • 建立网站 用英语wordpress网站调用导航菜单
  • 市中移动网站建设四川城乡建设网站证件查询
  • 大型建设工程类考试辅导网站镇江网站建设和优化推广多少钱
  • 网站开发php支付接口企业网站建设周期
  • 网站开发及服务器总共多少钱wordpress添加文件
  • 网站做好后多用户电商平台
  • 预定型网站有哪些网络服务费税收分类编码
  • iis做外网站点爱客crm软件
  • 郑州专门做网站的公司搜索引擎yandex入口
  • 邯郸做wap网站的公司网络推广好不好干
  • 专业做公司logo的网站软件行业发展前景
  • 查询网站备案进度查询网站域名的组成
  • 安徽省建设安全监督站的网站企业网站系统详细设计
  • 廊坊网站建设方案开发赣州网上问政
  • 网站推广具体内容简要说明做360手机网站优化排
  • 成都装饰公司网站建设做网站白云区
  • 高端网站定制建设公司哪家好网站策划书编写