文档章节

OkHttp完全解析(三)并发

k
 kim366
发布于 2016/05/13 19:08
字数 1452
阅读 21
收藏 0
点赞 2
评论 0

HttpURLConnection 的API是阻塞是的API,通过创建一个写入阻塞发送一个请求,通过一个读取阻塞接受响应。

[源码分析:4.2] 框架连接FramedConnection

 

4.1 阻塞式API

阻塞式API因其自上而下的程序代码而显得方便实用。网络调用跟其他普通方法调用一样:请求数据,返回。如果请求失败,则获得一个指向调用的堆栈跟踪。

阻塞式API可能会很低效,因为等待网络期间,线程处于闲置状态。但是线程是昂贵的,因为其建立在内存和上下文之上。

4.2 框架协议Framed Protocol 

框架协议根spdy/3和http/2一样,不会导致自身阻塞API。每个应用层线程都希望因为特定流阻塞I/O,但是在Socket中,流是多路复用的。线程不允许直接和socket对话,而是要与共享这个socket的其他应用层线程合作。在单个阻塞线程上,直接实现spdy/3或者http/2的框架规则是不切实际的。流控制特性在读取和写入之间引进反馈,要求写入告知读取,读取节制写入。

OkHttp中,在框架协议上暴露了阻塞API,这篇文档解释了使其工作的代码和原理。

注:SPDY(读作“SPeeDY”): Google开发的基于TCP的应用层协议,用以最小化网络延迟,提升网络速度,优化用户的网络使用体验。SPDY并不是一种用于替代HTTP的协议,而是对HTTP协议的增强。新协议的功能包括数据流的多路复用、请求优先级以及HTTP报头压缩。谷歌表示,引入SPDY协议后,在实验室测试中页面加载速度比原先快64%。(参见附件《SPDY》)

 

4.3 线程

4.3.1 应用的线程调用

应用层必须阻塞写入I/O,在我们将字节写入到socket之前,不能从一个写入中返回。否则,如果写入失败,我们将无法把一个IOException传递到应用中。我们应该告知应用层是否写入成功或者失败。

应用层也可以阻塞写入操作。如果应用程序请求从一个没有任何东西的地方读取数据,则需要持有那个线程,直到字节到达,流关闭,或者超时消逝。如果持有一些字节,但是没有任何其他地方需要他们,则应该将其放置到缓冲区中。从流量控制方面讲,在他们被应用消费掉之前,不应认为被传递出去了。假设有一个基于http/2的视频流。假设用户暂停了媒体播放,应用停止从流中读取字节。这个时候缓冲区会被填满,流控制会阻止服务器再往这个流中发送数据。当用户继续播放视频流时,缓冲区会被排放,读取被确认,服务端继续流出数据。

4.3.2 共享读取线程

不能依赖应用线程从socket中读取数据。应用线程是短暂的: 有时候,他们正在读取或者写入数据,有时候,他们停止做有关于应用层的事情。但是socket是永久的,并且需要持续的关注,比如我们分发所有进入的框架帧,以使应用层需要它时连接正常。

所以,我们为每个socket创建专用线程,专门读取框架帧并分发他们。

读取线程始终不应运行应用层代码。否则,一个缓慢的流就会拦截整个连接。

同样的,读取线程始终不应该阻塞写操作,否则可能导致锁死连接。试想,客户端和服务端都违反了这个规则。那么,如果运气不好的话,他们会填满整个TCP缓冲区(导致写阻塞),然后使用它们的读取线程进行去写入帧。没有其他地方从另一端读取数据,缓冲区也会被消耗完。

4.3.3 Do-stuff-later pool 

有时候,会存在调用应用层或者响应一个ping操作的动作,而发现这个工作的线程和应该处理这些工作的线程不一致。我们就会在线程池中加入一个线程对象,并且由线程池中的另一个线程进行处理。

4.4 锁

有三种不同的事件同步。

4.4.1  SpdyConnection

这种锁会守护每个连接的内部状态。这种锁不阻塞操作。这就意味着,我们获取一个锁,读取或者写入一些属性,然后释放锁。而没有I/O和应用层回调。

4.4.2  SpdyStream

这种锁会守护每个流的内部状态。跟上面一样,是不阻塞操作。当我们需要持有一个应用线程阻塞读操作时,我们必须通知或者等待这个锁。因为当wait()处于等待状态时,这个锁会被释放。

4.4.3  FrameWriter

   Socket的写是被FrameWriter守护的。同一时刻只有一个流可以写入,所以消息不交叉。写操作要么由应用层线程完成,要么由填充池完成。

4.5 持有多重锁

持有一个FrameWriter锁的同时,你可以持有一个SpdyConnection锁。但是,反过来不可以。因为持有一个FrameWriter锁可能引起阻塞。对于记账本来说,在创建一个流的时候这样做是有必要的。好的框架,要求在socket中,流的ID是连续的,所以我们需要和发送的流框架绑定设定的ID。

© 著作权归作者所有

共有 人打赏支持
k
粉丝 1
博文 129
码字总数 0
作品 0
朝阳
说说在 Android 中如何发送 HTTP 请求

客户端会向服务器发出一条 HTTP 请求,服务器收到请求后会返回一些数据给客户端,然后客户端再对这些数据进行解析与处理。 1 HttpURLConnection 可以使用 HttpURLConnection(官方推荐) 来发...

deniro ⋅ 06/09 ⋅ 0

spring传统xml配置okhttp3

问题 后端服务需要使用http客户端请求其他服务支持,项目中需要将HttpClient换成OKhttp,为啥要换OKhttp?这里不讨论这两者之间的优缺点。这篇文章主要关注与Spring传统xml配置方式集成Okhtt...

亚林瓜子 ⋅ 04/19 ⋅ 0

Android逆向之旅---爆破一款资讯类应用「最右」防抓包策略原理分析

一、逆向分析 首先感谢王同学提供的样本,因为王同学那天找到我咨询我说有一个应用Fiddler抓包失败,其实对于这类问题,我一般都会这么回答:第一你是否安装Fiddler证书了,他说他安装了。第...

jiangwei0910410003 ⋅ 04/25 ⋅ 0

Android面试的那些答不上来的问题(一)--- OkHttp的拦截器你到底了解多少(上)

前言 前段时间面试了很多家公司(坐标成都,大大小小加起来得20家吧),有时候有些事做多了,你就会发现它的一些窍门或者规律,面试这件事当然也不例外。其实很多公司问到的问题都大同小异,...

SillyMonkey ⋅ 05/10 ⋅ 0

Retrofit源码分析之OKHttpCall

之前在Retrofit源码初探一文中我们提出了三个问题: 什么时候开始将注解中参数拼装成http请求的信息的? 如何产生发起http请求对象的? 如何将对象转换成我们在接口中指定的返回值的? 其中第...

低情商的大仙 ⋅ 05/13 ⋅ 0

Android面试有迹可循(一)OkHttp3.9拦截器原理与区别

接上回 传送门 上回我们讲到,OkHttp的请求过程中有个非常重要的东西-“拦截器”,而且拦截器又分为interceptors和networkInterceptors两种,那它们具体有何区别呢?又要怎么来使用?现在来一...

SillyMonkey ⋅ 05/19 ⋅ 0

OkHttp3源码解析内部缓存

OkHttp3系列文章 OkHttp3 源码解析执行流程 OkHttp3 源码解析 连接池的复用 如果有了解过OkHttp的执行流程,可以知道,在拦截器链中有一个缓存拦截器CacheInterceptor,里面决定了是由缓存中...

Gillben ⋅ 05/22 ⋅ 0

Android Retrifot2简单使用学习

简介 Retrofit是一个现在比较火的网络请求框架,它的底层是依靠okhttp实现的(okhttp也是一款很不错的框架之前有使用过),确切的讲,Retrofit是对okhttp的进一步封装,它功能强大,支持同步...

reggie1996 ⋅ 05/27 ⋅ 0

[Tools] [okHttp] 调试笔记 --- 无法找到FormEncodingBuilder类

背景: 网上很多例子在讲okHttp的post和get时会用FormEncodingBuilder来构建RequstBody。 但是在okHttp3上,此接口已经已经变掉了,替代它的是MultipartBuilder。 官方说明: okHttp3所有改动...

kris_fei ⋅ 05/25 ⋅ 0

[工具安装使用] [Websocket] Wesocket Client测试用例

利用okHttp中的WebSocket功能在AndroidStudio测试WebSocketClient, 其中Server是使用okHttp中的moc web server搭建的,所以在同一台机器上测试的(moc只能在本机上测试),如果没有搭server, 可...

kris_fei ⋅ 05/11 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

内核线程、轻量级进程、用户线程

线程与进程概念 在现代操作系统中,进程支持多线程。 进程是资源管理的最小单元; 线程是程序执行的最小单元。 即线程作为调度和分配的基本单位,进程作为资源分配的基本单位 一个进程的组成...

117 ⋅ 18分钟前 ⋅ 0

elasticsearch2.4.6升级为elasticsearch-5.5.0的经历

将elasticsearch-5.5.0 中的配置 path.data 指向原来的数据路径 即 path.data: /usr/local/src/elasticsearch-2.4.6/data 注意: elasticsearch-5.5.0 需要将jdk版本升级到1.8...

晨猫 ⋅ 19分钟前 ⋅ 1

lvm讲解 磁盘故障小案例

1

oschina130111 ⋅ 23分钟前 ⋅ 0

那些提升开发人员工作效率的在线工具

本文转载自公众号 Hollis 作为一个Java开发人员,经常要和各种各样的工具打交道,除了我们常用的IDE工具以外,其实还有很多工具是我们在日常开发及学习过程中要经常使用到的。 Hollis偏爱使用...

时刻在奔跑 ⋅ 35分钟前 ⋅ 0

restful风格 实现DELETE PUT请求 的web.xml的配置

import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframe......

泉天下 ⋅ 40分钟前 ⋅ 0

Shell数组

Shell数组 Shell在编程方面比Windows批处理强大很多,无论是在循环、运算。 bash支持一维数组(不支持多维数组),并且没有限定数组的大小。类似与C语言,数组元素的下标由0开始编号。获取数...

蜗牛奔跑 ⋅ 50分钟前 ⋅ 0

nmap为了开发方便 可以做简单的修改

因为nmap扫描是默认使用的是nse脚本,但是在开发的过程中需要修改后缀(主要是因为后缀为lua才能显示高亮,所以这里用一个取巧的办法) nse_main.lua文件中我们找到如下代码 local t, path = cn...

超级大黑猫 ⋅ 54分钟前 ⋅ 0

springmvc获取axios数据为null情况

场景:前端用了vue没有用ajax与后台通信,用了axios,但是在代码运行过程中发现axios传递到后台的值接受到数据为null。 问题原因:此处的问题在与axios返回给后台的数据为json类型的,后台接...

王子城 ⋅ 56分钟前 ⋅ 0

hadoop技术入门学习之发行版选择

经常会看到这样的问题:零基础学习hadoop难不难?有的人回答说:零基础学习hadoop,没有想象的那么难,也没有想象的那么容易。看到这样的答案不免觉得有些尴尬,这个问题算是白问了,因为这个...

左手的倒影 ⋅ 56分钟前 ⋅ 0

806. Number of Lines To Write String - LeetCode

Question 806. Number of Lines To Write String Solution 思路:注意一点,如果a长度为4,当前行已经用了98个单元,要另起一行。 Java实现: public int[] numberOfLines(int[] widths, Str...

yysue ⋅ 今天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部