文档章节

OkHttp完全解析(三)并发

k
 kim366
发布于 2016/05/13 19:08
字数 1452
阅读 55
收藏 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之OkHttp详解

文章大纲 一、OkHttp简介 二、OkHttp简单使用 三、OkHttp封装 四、项目源码下载 一、OkHttp简介 1. 什么是OkHttp   一般在Java平台上,我们会使用Apache HttpClient作为Http客户端,用于发...

故事爱人
04/03
0
0
Android 网络优化,使用 HTTPDNS 优化 DNS,从原理到 OkHttp 集成

一、前言 谈到优化,首先第一步,肯定是把一个大功能,拆分成一个个细小的环节,再单个拎出来找到可以优化的点,App 的网络优化也是如此。 在 App 访问网络的时候,DNS 解析是网络请求的第一...

承香墨影
03/25
0
0
Android技能树 — 网络小结之 OkHttp超超超超超超超详细解析

前言: 本文也做了一次标题党,哈哈,其实写的还是很水,各位原谅我O(∩_∩)O。 介于自己的网络方面知识烂的一塌糊涂,所以准备写相关网络的文章,但是考虑全部写在一篇太长了,所以分开写,...

青蛙要fly
2018/11/13
0
0
OKHttp源码分析1 - 框架

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013510838/article/details/52424637 1 OKHttp介绍 网络库一直是Android APP开发中至关重要的库,关系到加载...

谢杨易
2016/09/03
0
0
Android开发之OkHttp介绍

要论时下最火的网络请求框架,当属OkHttp了。自从Android4.4开始,google已经开始将源码中的HttpURLConnection替换为OkHttp,而在Android6.0之后的SDK中google更是移除了对于HttpClient的支持...

#Temptation
08/26
0
0

没有更多内容

加载失败,请刷新页面

加载更多

centos 查看删除旧内核

1、查看系统中安装的内核 $ yum list installed | grep kernel 2、删除系统中旧内核 $ yum install yum-utils$ package-cleanup --oldkernels --count=2...

编程老陆
39分钟前
7
0
ES6

ES6:不改变原理的基础上,让API变得更简单 一、let:代替var用于声明变量 1、var的缺点: (1)声明提前 (2)没有块级作用域 2、let的优点: (1)组织了申明提前 (2)让let所在的块({}),...

wytao1995
今天
3
0
kubernetes 环境搭建 —— minikube

创建集群 minikube start 搭建好 k8s 集群后,可以查看集群的状态以及部署应用。主要用到的是 k8s 的 api,这通常需借助于 kutectl 命令行工具 基本操作 kubectl versionkubectl cluster-i...

lemos
今天
9
0
关于js混淆与反混淆还原操作

使用js的混淆加密,其目的是为了保护我们的前端代码逻辑,对应一些搞技术吃饭的公司来说,为了防止被竞争对手抓取或使用自己的代码,就会考虑如何加密,或者混淆js来达到代码保护。 1、为什么...

开源oschina
今天
11
0
用盛金公式解三次方程(ansi c版)

/* cc cubic.c -lm gcc cubic.c -lm Shengjin's Formulas Univariate cubic equation aX ^ 3 + bX ^ 2 + cX + d = 0, (a, b, c, d < R, and a!= 0). Multiple root disc......

wangxuwei
今天
9
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部