分为

1.入口的队列、线程池处理

2.若干拦截器

3.连接池

4.Okio

 

Okio

在BIO眼中,有字符流,字节流

字符流:sofjasiofj你好*……*&%&*

字节流:0101010101

BIO、NIO、Okio

BIO本质是操作数组,所以我们一般都是新建一个byte[]来作为缓冲区的。

NIO引入buffer、channel、selector的概念,类似epoll,selector会监听多个channel,最终实现单线程处理多连接的就绪情形

Okio本质是封装的BIO,所以是阻塞的

Buffer

buffer中有许多segment,每个segment都是数组,若干segment形成一个双向循环链表,同时还有一个segment单链表池管理segment

每两个sement如果小于一半,可以进行合并,同时回收一个segment

在拷贝的时候,采用System.arraycopy

如果重复部分大于1KB,转为共享,使之不可变

ByteString

处理不可变数据很不错。内部维护String、byte[],转型起来几乎不费时间

超时检测

同步,每次循环都会遍历一个segment的长度,每次都会计时一次。

异步是看门狗线程,在处理socket的流的时候是异步的。看门狗里维护所有时间统计的单链表。在插入链表的时候,按剩余时间来,插入到头部,剩余时间最少,这个时候看门狗会被notify。在检测第一个链表的剩余时间后,会wait剩余时间。在链表为空后,会wait1分钟。

 

连接池

keep-alive(HTTP1.x)

保活6-8个TCP连接

多路复用(HTTP2)

分解成二进制帧,指定流优先级,在发送端拆解,在接收端组装。在TCP连接之上,还有一个数据流的概念

数据结构

双向队列、数组实现

stream匹配connection规则

1.查找可复用的连接

2.配置路由,配置后再从连接池中找可复用连接

3.新建连接,修改标记计数,放入连接池中

4.查看连接池重复的多路复用连接,并清除,因为他们复用一个就可以了

get规则

1.非host域必须一样

2.host域也一样,就可以复用

3.host不同,但是在HTTP2域名切片场景下,依然是可以复用的

清除多余connection:

主要针对HTTP2的多路复用连接,希望他们复用同一个,而不是各自都匹配一个,如果有,清除他们。

自动回收

内部有一个清洁工线程,每次清理后,都会wait一段时间

外部notify时机:

1.在put新连接的时候

2. connectionBecameIdle

回收规则:

1.标记所有空闲连接 

2.如果空闲连接超过5个,且保活时间大于5分钟,清除当前被标记的连接,同时立刻再次扫描

3.如果没有超过5个,这个线程沉睡快到期的时间连接的剩余时间

4.如果全部是活跃的,那就5分钟执行一次

 

入口的队列、线程池处理

同步任务

会被加到deque中

开始执行任务

移除deque

异步任务

请求数小于64、单一host小于5,加入运行队列,并给到线程池

否则加入等待队列

每个执行执行完后,都会重复第一条判断

线程池

cache型

 

拦截器——缓存

HTTP缓存规则在CacheStrategy中的实现

HTTP 1.0

强制缓存 expires(服务器返回的到期时间)

对比缓存 if-modified-since(服务器上次返回的资源最后的修改时间)/Last-Modified(服务器返回资源最后的修改时间)

HTTP 1.1

强制缓存 cache-control(一般在response中,指定多少时间内可复用)

对比缓存 if-none-match(服务器上次返回的资源号)/e-tag(服务器返回最新的资源号)

(此外还有,Date-响应的出生日期,Age-从缓存中拿到响应时响应的年龄。会结合cache-control的stale、fresh来处理过期但仍旧使用response的逻辑,不过会打警告。还会检测HTTPS请求有没有TLS握手)

大体逻辑

CacheStrategy其实和HTTP浏览器缓存规则相似,分为强制和对比。还有一个Cache类,内部维护DiskLruCache,通过requestCount、hitCount、networkCount来优化缓存指标。

 

拦截器——桥梁

我们的请求与相应都是一些简单的对象,其实比之真正的请求,还少了不少字段,比如content-length、transfer-encoding等。这个拦截器做的工作就是加上这些字段。

 

拦截器——重试、重定向

内部开启一个循环,用于在请求失败后,重新发送请求;在重定向后,重新请求(有两种),倾向于复用同一个连接。

 

拦截器——真正网络请求

其实就是Socket编程,Okio封装流操作,此外注意有试探性请求,通过Exactra

 

哎,太懒了,不想一行代码一行代码去看了。应付面试官应该够了。