参考文章《HTTP协议:菜鸟入门系列》 - 老_张 - 博客园
参考文章 HTTP2 详解 - 简书
参考文章 HTTP2.0协议全文翻译
参考文章 探索HTTP/2: 流的状态(原) - John Jiang - BlogJava
HTTP/1.x
http1.x是基于文本的通信协议,分为start line(请求行),http header(请求头)和http body(请求体)三个部分。
根据发起方的不同
- start line又分为request line(请求行) 、status line(状态行)
- http header又分为request header(请求头) 、response header(响应头)
- http body又分为request body(请求体)、response body(响应体)
*进行http通讯之前必须先建立tcp连接,完成三次握手
请求行
http请求的第一行是请求行,记录请求类型(get、post等)、请求URI、协议版本(http1.0、http1.1等),在http请求的第一行,以\n结尾,第二行开始才是请求头
请求头
请求头从第二行开始,用来标识
- 请求体长度(必传)
- 能够接受的数据类型
- 语言
- 浏览器信息
- 压缩方式
- 编码方式
- host
- cookie
- 等
请求头是变长的,以连续两个\n为结束标识(即空一行)
不同类型的请求请求头不一样,相同类型下有些请求头字段可以不传
请求体
请求体没有格式要求,可以根据应用实际情况灵活处理,唯一一点要求就是必须要和请求头之间空一行。
状态行
响应的第一行是状态行,返回该次响应的协议版本(http1.0、http1.1等)、请求的状态(200、404、500等)、状态描述
响应头
响应头与请求头类似,都包含了一些关于请求本身的信息,可能包括
- 重定向时的新地址
- 服务器信息
- 编码格式
- 响应体长度
- 响应体语言
- 过期时间
- 等
响应头是变长的,以连续两个\n为结束标识(即空一行)
响应体
响应体也没有格式要求,可以根据实际情况灵活处理,唯一一点要求仍然是必须要和响应头之间空一行。
http请求头内容是http协议中非常重要的一块内容,知识点也很多。这几篇文章详细介绍了请求头的内容
http协议(六)报文首部 - 老_张 - 博客园
http协议(七)通用首部字段 - 老_张 - 博客园
http协议(八)请求首部字段 - 老_张 - 博客园
http协议(九)响应首部字段 - 老_张 - 博客园
http协议(十)实体首部字段 - 老_张 - 博客园
HTTP/1.0与HTTP/1.1的区别
- 支持的请求方法不同,http1.0不支持OPTIONS、TRACE、CONNECT三种请求方式,http1.1不支持LINK和UNLINK两种请求方式。其中,CONNECT(隧道协议)方式用来进行SSL\TLS加密通讯,所以http1.0自然也不支持https。
- http1.0没有host请求头,意味着http1.0不支持在一台http服务器上搭建多个web站点。比如,你不能同时在一台服务器上托管www.baidu.com和www.taobao.com两个域名。而http1.1协议里host一定要传
- http1.0默认都是非持久连接,一次http请求完成后就会断开;http1.1默认都是持久连接,一次连接后可以持续发送请求,直到一方断开连接
- http1.1支持长链接,自然地会发展出管线化技术(pipeline),http1.0只有部分服务器通过非标准手段实现了长链接,所以不一定支持管线化
- HTTP/1.1加入了一个新的状态码100(Continue)。
- HTTP/1.1加入了一些cache的新特性,当缓存对象的Age超过Expire时变为stale对象,cache不需要直接抛弃stale对象,而是与源服务器进行重新激活(revalidation)。
- HTTP/1.1引入了Chunked transfer-coding来将消息分割成若干个任意大小的数据块,避免缓冲整个消息带来的过载。
http1.1主要是在1.0的基础上优化性能,以及通过扩展http header的方式增加了部分功能。1.1相当于1.0的特性增强版
HTTP/2.0
http2.0是基于SPDY协议设计出来的、基于二进制帧流的通信协议。(SPDY协议与http2差别不大,就不单独介绍了)
每一个二进制帧都分为length(24bit)、type(8bit)、flags(8bit)、预留位(1bit)、streamID(31bit)、payload(任意长度)六个部分。其中length、type、flags、预留位、streamID组成了帧头(frame header),固定长9字节(72比特)。
- length:表示payload部分的长度,默认大小为0~16,384(214)
- type:表示此帧的类型,一共10种
- flags:重要参数位,没一bit位代表一个参数
- 预留位:预留
- streamID:表示此帧的顺序,用作流控制
- payload:正文
http2.0的帧是比http1.1中的请求更小的传输单位,且http1.1的请求可以被封装到http2.0的帧里。每一个请求都可能对应多个帧的交互。
每一帧的正文长度默认都不超过16384(214)比特,除非接收方通知了SETTINGS_MAX_FRAME_SIZE(一般在214到224之间)
帧的种类(type):
类型 | 对应类型码 | 说明 |
---|---|---|
DATA | 0x0 | 数据帧,传输应用需要的数据 |
HEADERS | 0x1 | 消息头帧,传输头信息,包括请求头、响应头等 |
PRIORITY | 0x2 | 优先级帧,设定流优先级 |
RST_STREAM | 0x3 | 流终止帧,中断流或者表示发生了一个错误,不中断连接 |
SETTINGS | 0x4 | 设置帧,设置该连接的参数,作用于整个连接 |
PUSH_PROMISE | 0x5 | 推送帧,服务端推送时使用,客户端可以返回一个RST_STREAM 帧来拒绝推 |
PING | 0x6 | PING帧,判断空闲连接是否可用,测量最小往返时间 (RTT) |
GOAWAY | 0x7 | GOAWAY帧,发起关闭连接,或者警示严重错误。关闭连接前会处理完已建立的流 |
WINDOW_UPDATE | 0x8 | 窗口更新帧,流量控制。可以针对某个流,也可以针对整个连接 |
CONTINUATION | 0x9 | 延续帧,示意继续传输数据 |
每一种类型的帧都有特定的格式, |
其中HEADERS帧和DATA帧用来兼容http1.x,分别对应1.x中的消息头和消息体。
流和多路复用
流(stream)是一个逻辑概念,表示双向交换的独立的帧序列,由帧头(frame header)中的streamID标识。http2.0定义了高度独立的流来实现高效率的多路复用,任意流的阻塞不会影响其他流的处理。并且每一个流都可以有一个独立的优先级,用来帮助对端分配资源,挑选重要的信息优先传输。
流是有状态的,并且在整个交互周期内会出现状态的流转,流的状态流转是通过不同类型的帧来控制的。详细情况在另一篇文章中有说明(还没写)
流量控制
请求发起方可以主动要求服务器只传输指定大小的数据,服务端在传输完成后会暂停流,直到客户端要求继续传输后面的数据。在某些场景下,这种机制可以极大的缓解网络压力,并且降低网页感知渲染时间。
服务器主动推送
有了高度独立的流和多路复用机制,http2.0可以很容易的实现服务器主动推送的功能。即在tcp连接上服务端主动发起一个PUSH流,当然客户端也可以拒绝。
压缩消息头
http2.0针对消息头做了很大程度的压缩:
- 通讯双方各自维护一份索引表(头列表),将常用的请求头维护到索引表中,通讯时直接发送索引号,而不是字符串,部分常用请求头信息的索引是硬编码的,不需要动态维护
- 需要发送字符串的情况下,使用哈夫曼编码压缩字符串
http2.0中的头字段与1.1的格式一样。当通讯双方需要交换头列表时,先将若干个头字段集合成头列表,再通过HPACK压缩算法压缩成头部块,然后将过大的头部块拆成若干头部块段,通过HEADERS帧、PUSH_PROMISE帧、或者CONTINUATION帧的payload进行传输。而Cookie字段比较特殊,需要特殊处理,详见Hypertext Transfer Protocol Version 2 (HTTP/2)
加密
http2.0协议不强制要求信息加密。对于没有安全层的http2.0实现,称其为 HTTP/2 Cleartext (h2c)
目前,各大浏览器都不打算支持h2c,所以常见的http2.0基本都是基于https的
很多http2.0的工具和类库同时支持 h2 和 h2c,支持的工具清单
不足之处
- 单连接开销比较大。HPACK数据压缩算法会更新两端的查找表。这样可以让连接有状态,而破坏状态就意味着要重建查找表,另外单连接占用内存较多。
- 你可能不需要SSL。如果你的数据不需要保护,或者已经使用DRM或其他编码进行保护了,那么TLS的安全性对你可能无所谓。如果C/S两端都能由你自己控制的话,可以自己实现h2c,然后这个点就不再是问题了
- 需要抛弃针对HTTP/1.x的优化。HTTP/1.x优化在支持HTTP/2的浏览器中会影响性能,因此可能需要花时间把它们推倒重来。(比如分域存储)
- 对下载大文件不利。如果你的应用主要提供大文件下载或者流媒体播放,那可能不想用TLS,而且在只有一个流的情况下,多路复用也体现不出什么优势。
HTTP/2.0与HTTP/1.x的区别
http2.0和1.x在报文格式上区别很大,但是语义、状态码、请求方法没有什么区别
- http2.0使用的是二进制格式协议,比起http1.x的明文格式协议健壮性和效率都提升了很多
- http2.0定义了stream双向帧流,可以在一个tcp连接内混杂发送多个stream的消息,而不必像http1.x中的管道化技术,必须等前一个响应完成后再发送后面的响应(HOLB,Head-Of-Line Blocking)
- http1.x传的都是明文,安全性很差
- http1.x每次请求和响应都需要带上完整的header,增加了不少网络开销
- 使用1.x协议时每个网页可能需要打开多个TCP连接来请求数据,而浏览器对每个域名打开的连接数又有限制;2.0协议可以只打开一个tcp连接,一个连接上能够支持上百个并发的流传输数据。相当于把tcp当成一个平台,在这个平台之上进行设计,实现各种花式特性
- http2.0可以兼容http1.x,或者说http2.0包含了http1.1
- 虽然http2.0的协议不强制要求TLS层,但实际上所有浏览器实现时都要求必须有TLS层,所以现有的http2.0基本都依赖https,