文档章节

OkHttp完全解析(三)并发

k
 kim366
发布于 2016/05/13 19:08
字数 1452
阅读 25
收藏 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。

本文转载自:http://blog.csdn.net/oyangyujun/article/details/50039253

共有 人打赏支持
k
粉丝 1
博文 129
码字总数 0
作品 0
朝阳
Android中流行的第三方库资源收集

1、GSON GSON是将JSON解析成POJO的Java库。GSON也可以将POJO解析成JSON。 2、OkHttp OKHttp是Android版Http客户端。非常高效,支持SPDY、连接池、GZIP和 HTTP 缓存。默认情况下,OKHttp会自动...

jdroid
2014/05/02
0
0
说说在 Android 中如何发送 HTTP 请求

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

deniro
06/09
0
0
手写Android网络访问框架OkHttp(简易版)

开篇废话 趁着周末两天的时间,跟着大神的脚步,把我们经常使用的网络框架OkHttp的源码好好跟了一下,初次观看,确实非常容易钻进去,搞得云里雾里,在大神的指导下,才勉强把整个逻辑走通。...

进击的欧阳
05/06
0
0
feign和okhttp的结合

背景 使用feign可以很方便的调用各种http接口 http请求神器之Feign 那么feign是如何做到的呢? 分析 本质上默认场景feign仍然是使用httpClient进行调用的。 通过声明式的RequestMapping等注解...

Mr_Qi
07/11
0
0
spring传统xml配置okhttp3

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

亚林瓜子
04/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

CentOS 7.* 配置网络

配置静态IP 进入配置文件目录 cd /etc/sysconfig/network-scripts 查找以 ifcfg-eno 开头的文件并编辑它 vi ifcfg-ens32 修改文件中的变量值 BOOTPROTO=staticONBOOT=yesIPADDR=192.168...

阿白
31分钟前
0
0
深入理解OAuth2.0协议

1. 引言 如果你开车去酒店赴宴,你经常会苦于找不到停车位而耽误很多时间。是否有好办法可以避免这个问题呢?有的,听说有一些豪车的车主就不担心这个问题。豪车一般配备两种钥匙:主钥匙和泊...

xtof
36分钟前
1
0
Linux学习-0920

3.4 usermod命令 3.5 用户密码管理 3.6 mkpasswd命令 一、usermode命令 usermode作用是用来修改用户信息。 方法: usermod 参数 username 示例1:修改用户uid usermod -u 1010 test5 示例2...

wxy丶
45分钟前
1
0
synchronized锁对象的坑

今天本来写点其他东西,碰巧写了一下synchronized,没想到掉坑里面了,大佬别笑。 起初代码大概是这样的: package com.ripplechan.part_1_2_3;import java.util.concurrent.CountDownL...

RippleChan
49分钟前
1
0
XAMPP环境搭建(Apache + MariaDB + PHP + Perl)

operation system:ubuntu-18.04.1 step1:download XAMPP #sudo wget https://www.apachefriends.org/xampp-files/7.2.9/xampp-linux-x64-7.2.9-0-installer.run step2:install XAMPP #sudo ......

硅谷课堂
51分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部