HTTP2 学习

1、HTTP1.x存在的问题css

      Http1.0时Connection没法复用,同一时间一个Connection只能处理一个request。Http1.1引入了Request pipelining来解决这一问题,Request pipelining。html

  Requestpipeling在FIFO基础上支持同一Connection并发处理多个Request,这里的FIFO是指Http Response发送顺序必须与Request的发送顺序保持一致。
  详情前往https://en.wikipedia.org/wiki/HTTP_pipelininggit

  然而它并不完美,仍然有HOL Blocking问题。github

     

  所谓的行首阻塞是因于FIFO的缘由,致使后面的Reponse因为其以前的Response因为资源抢占等缘由没法输出而Block。编程

  因为这样的限制,HTTP/1.0及HTTP/1.1时代须要对Server端建立多个链接,经过提升并发度来下降Latency。windows

  另外Http2支持Header压缩,而Header压缩在此前是不支持的,此前通常是对body进行gzip压缩。浏览器

 

2、HTTP2的解决方案缓存

  HTTP2在协议上真正要求不一样的Request能够在同一个Connection上交错进行,真正作到多路复用。所带来的好处显而易见,更少的Connection,更好的并发,更高效的网络资源利用。服务器

  支持流量控制及请求优先级,使得重要的请求优先获得处理,这一点对于应用来讲是个大的优化点,以体验为目标,对不一样的请求划分优先级以及流量控制,好比异步加载的内容重要性低,能够设置较低优先级。可是我的以为这一点要作好很难,要依赖于浏览器,应用服务器,应用程序三个地方都有很是好的实现,是不是合理的实现还须要好的度量平台,视效果而定。网络

  Server Push机制支持Server端应用程序能够预先输出内容暂未须要的内容,从而下降潜在的延时。举例:能够把css内容与html内容同步输出,而不须要等待html彻底输出后,浏览器再加载css。

  支持对Http Header进行压缩。

  高效的二进制格式(相对文本格式)传输。

3、原理分析

   

  将经过Jetty源码来分析Jetty如何支持Http2的
  Jetty源码地址:git://git.eclipse.org/gitroot/jetty/org.eclipse.jetty.project.git

  A. Jetty.io&Jetty.server主要类结构图:

Jetty.io主要是对EndPoint及Connection的定义和基本实现,Jetty.server实现了络的交互过程,包装了Socket,Channel,多路复用等实现。这两个包一块儿对应用程序端或协议格式端提供了网络交互过程,从而实现网络交互过程对于协议及应用的透明。

B. 与Http2协议的结合:

  Jetty Basic如上图已经介绍,HTTP2的实现只扩展ServerConnection,ServerConnectionFactory便可,至关于Jetty内核上增长插件,扩展性好,另外也不须要关注网络细节

C. 对重点类的重点解读:

 

类名 职责 详细介绍
HTTP2Flusher Frame输出控制类 重点说明:
HTTP2Flusher类中保存了各类Entry队列,Entry中包含Frame数据,其对应的Stream引用,以及对应的CallBack。
主要属性: 
Queue<WindowEntry> windows,WindowUpdateFrame类型的保存队列
ArrayQueue<Entry> frames,Frame数据队列 
主要方法:
window(), prepend(), append(), remove()等都是针对如上Queue的操做
process()真正执行Frame的输出。首先执行Window队列,将Window的窗口设置数据写入到对应的Stream或Session中;而后执行WindowsSize的限流逻辑,若对应的Session或Stream当前WindowSize不大于0,则不发送Frame,不然将WindowSize减去当前Frame的Size,应用于下次限流。最后调用Session中的EndPoint类的write方法将Frame输出
FlowControlStrategy 流控接口定义 重点说明: 
其实现类主要实现了依据发送或接收的Frame的数据length,依据固定策略改写Session及Stream的WindowSize,以及Stream另外一端EndPoint对于WindowSize的要求,完成输科和输出限流的完整逻辑
Http2Session ISession的实现类 主要属性:
1. EndPoint endPoint, 表征了此Session的网络端点,对于网络的操做经过调用endPoint的方法实现
2. Generator generator,用于按需生成各类格式的Frame,Frame被最终写入endPoint中 
3. Listener listener,Session中被动接口的逻辑实现,面向接口编程,支持多种实现
4. FlowControlStrategy flowControl前面已经讲述
5. HTTP2Flusher flusher前面也已讲述
主要方法:
1.newStream(),建立新的流对象,以及HeaderFrame,将流写入Session的流缓存中,流缓存经过ConcurrentHashMap实现;并将流和HeaderFrame追加到Http2Flusher对象的ArrayQueue中;
2. push(), settings(), ping(), reset()的实现雷同,最终都是将对应格式的Frame放入Http2Flusher的ArrayQueue中。Http2Flusher是真正输出Frame的控制类。
3. onData(),接收DataFrame时的处理方法,首先更新当前FlowControl对象中的WindowSize,并执行Window限流逻辑,若未超出限流控制,则调用Stream的处理方法处理接收到的数据,不然直接丢弃当前Frame,最后将WindowSize恢复以前值
4. onHeaders()接收HeaderFrame时的处理方法,抽象方法,交由子类实现
5. onPriority(),Jetty默认未支持客户端发起的对优先级的支持
6. onReset(), onSettings(),onPing(),onGoAway(),onWindowUpdate(),onConnectionFailure()执行对应逻辑,经过Listener接口,支持对于这些请求数据的自定义实现
HTTP2Stream IStream的实现类 重点说明: 
实现了IStream的主动接口及其被动接口Stream.Listener。其主动接口通常是经过调用对应的ISession接口实现
HTTP2ServerSession 继承HTTP2Session,实现Server端Session特有的逻辑 重点说明:
特有逻辑包括ServerSession在接收onPreface时,需回复一个Settings Frame;在接收Headers请求时需建立RemoteStream对象;当接收ServerPush时,报出异常,HTTP2中Client不能向Server发送Server Push。
DataFrame HTTP2协议的各类数据格式的封闭 重点说明: 
针对不一样的数据格式,如ServerPush,Preface等,有对应的子类实现
DataGenerator 构建如上的DataFrame 重点说明:
对于不一样的数据格式有不一样的子类实现
parser包 对接收的数据格式进行解析 重点说明:
对接收的数据格式进行解析

 

4、如何实现HTTP2

 

HTTP2还未被全部浏览器所支持,所以在实施时要支持多种协议并存.

须要Http Server端支持HTTP2协议,据我所知Tengine还没有支持,已支持的Server列表https://github.com/http2/http2-spec/wiki/Implementations

若要充分利用HTTP2的全部优势,须要在应用程序端(甚至是JAVA)的输出行为做智能处理,如经过大数据来分析哪些资源适合用Server Push并行输出,哪些资源优先级能够隐藏低,如何在性能与复杂度及维护成本之间作出平衡,须要业内更多的人努力和尝试,

相关文章
相关标签/搜索