ArgusAPM icon indicating copy to clipboard operation
ArgusAPM copied to clipboard

OkHttp 的拦截问题

Open dieyidezui opened this issue 5 years ago • 3 comments

简单粗略的扫了一下,其他的没看,简单的看了 OkHttp 的部分。

说实话 OkHttp 的拦截非常有问题

OkHttp3Aspect

在 OkHttpClient.Builder.build() 的时候添加一个 NetWorkInterceptor 拦截器,作为最外层的普通拦截器,忽略了内部的网络请求自动重定向/重试等多个 Http请求,且拿到的 Response 是转换后的(如自动解 Gzip)统计的结果自然不准确。

而且,这里添加的拦截器,会被 OkHttpClient.interceptors()方法暴露出去。如果有其他逻辑依赖这个方法,就会有问题。

其次,如果是 OkHttpClient.newBuilder(),那么在下次 build 时会有重复的多个拦截器,统计结果能准确吗。

个人认为最佳实践是在 RealCall.getResponseWithInterceptorChain方法内,调用 OkHttpClient.interceptors() 与 networkInterceptor() 时添加对应的拦截器。事实上如果要更多细节的数据,如 DNS TCP 时间等,可以通过 ThreadLocal 来处理数据的联动。

其实在 OkHttp 3.9.0 开始已经内置了 EventListener API 来提供多种事件的回调,可以作为参考。

NetWorkInterceptor

在这里统计 Response 的 length 时, 如果 Content-Length 为 -1,则 source().request(Long.MAX_VALUE)。 此处如果这个请求是下载某个大文件,那么 source().buffer() 里就会包含全部的字节数据,结果不言而喻。

此处提供一个思路

  1. 做一次探测,request 一个阈值,如果已经读完,自然皆大欢喜。否则
  2. 包裹 ResponseBody,在实际读取的时候记录字节数目。但是注意在读取过程中网络请求失败,则读取的字节数目是不全的,处理对应的上报逻辑即可。

以上。

dieyidezui avatar Nov 29 '18 03:11 dieyidezui

您好,针对该问题,我们会在后面的版本进行验证和修复,如有更多的想法请加入我们的官方QQ群(949010404)进行详细的沟通,谢谢! @dieyidezui

akathink avatar Nov 29 '18 06:11 akathink

行 和 头 好像也没统计 开源之前好歹参考下 stetho、flipper 吧

JWBlueLiu avatar Dec 12 '18 08:12 JWBlueLiu

行 和 头 好像也没统计 开源之前好歹参考下 stetho、flipper 吧

嗯呢,谢谢您的建议,后面我们会参考一下您说的项目,也可以提Pull Request,大家一起进步!

akathink avatar Dec 13 '18 04:12 akathink