HTTP协议探究(六):H2帧详解和HTTP优化

摘要:
但是,CONTINIUATION帧不能用于关闭流。EndSegment:位2标识当前端的最后一帧。标头:HTTP标头wireshark数据包捕获流:HEADERS,StreamID:25,Length51,POST/fd/ls/lsp。aspxLength:51Type:HEADERSFlags:0x24……..0=EndStream:False…..1.=EndHeaders:True…..0…..=填充:False…..1…..=优先级:True00.0...0...0.0...0=未使用:0x000……..=保留:0x00000000000000000000000011001=流标识符:251…………..=独占:True 00000000000000000000000000000000=流依赖性:0Weight:219 HeaderBlockFragment:83dd870084b958d33f8b625918a10c508ad71a2bf35c830b…标题:。初始值为4096字节SETTINGS_ENABLE_PUSH:服务器推送许可标志,默认启用。业务窗口的初始值为65535,业务窗口的负值表示禁止发送SETTING帧。例如,如果客户端在建立的连接上立即发送数据

一 复习与目标

1 复习

  • HTTP1.1存在的问题

  • HTTP2.0要兼容HTTP1.1

  • HTTP2.0的重要概念

    • 分帧层
    • 二进制:流 消息 帧
    • 流的状态、优先级和并发
    • 流量控制
    • 服务器推送
    • 首部压缩
  • HTTP2.0的流的建立(HEADERS或PUSH_PROMISE)和数据发送(DATA)

2 目标

  • 帧定义
  • HTTP2.0流量分析
    • Chrome插件:HTTP/2 and SPDY
    • WireShark
  • 对某些帧进行分析
  • HTTP优化

二 帧定义

1 HEADERS

(1)定义

img

  • 长度:16位,代表帧净荷最大可达65535字节(64KB),只有当Padded为1时才有效。
  • 类型:0x01
  • 标志:
    • End Stream:位1标识最后报头区块;一个HEADER帧太长时会分帧传输,后续跟着CONTINUATION 帧,如果CONTINUATION帧的END_STREAM标志为1,代表流传输结束。但是CONTINUATION帧并不能用于关闭流。
    • End Segment:位2标识当前端的最后一帧。
    • End Header:位3标识帧包含了整个的报头块且后面没有延续帧。
    • Padded:位4标识Pad Length字段会呈现。
    • Priority:位6标识专用标记、流依赖及权重字段
  • R:保留字段,1位
  • 流标志符:31位,唯一标识 HTTP 2.0 的流,流标识符为奇数(不包含1),1为升级协议使用。
  • 首部块:HTTP首部

(2)wireshark抓包

Stream: HEADERS, Stream ID: 25, Length 51, POST /fd/ls/lsp.aspx
	Length: 51
    Type: HEADERS (1)
    Flags: 0x24
    	.... ...0 = End Stream: False
        .... .1.. = End Headers: True
        .... 0... = Padded: False
        ..1. .... = Priority: True
        00.0 ..0. = Unused: 0x00
    0... .... .... .... .... .... .... .... = Reserved: 0x0
    .000 0000 0000 0000 0000 0000 0001 1001 = Stream Identifier: 25
    1... .... .... .... .... .... .... .... = Exclusive: True
    .000 0000 0000 0000 0000 0000 0000 0000 = Stream Dependency: 0
    Weight: 219
    Header Block Fragment: 83dd870084b958d33f8b625918a10c508ad71a2bf35c830b...
        Header: :method: POST
        Header: :authority: cn.bing.com
        Header: :scheme: https
        #......

2 DATA

(1)定义

img

  • 类型为0x0

注:基本上与HEADERS帧差不多,不过多介绍了。

(2)wireshark抓包

Stream: DATA, Stream ID: 25, Length 1316
	Length: 1316
	Type: DATA (0)
	Flags: 0x01
		.... ...1 = End Stream: True
		.... 0... = Padded: False
		0000 .00. = Unused: 0x00
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0001 1001 = Stream Identifier: 25
	Data: ......

3 SETTINGS帧

(1)定义

img

  • 类型为0x4

  • ACK标志:位1表示设置帧被接收端接受并应用。当ACK为1时,帧净荷必须为空.

  • 帧净荷为帧参数

    • SETTINGS_HEADER_TABLE_SIZE(1) :允许发送端通知远端终端解码报头区块的报头压缩表的最大承载量。初始值为4096字节
    • SETTINGS_ENABLE_PUSH(2) :服务器推送许可标志,默认开启。
    • SETTINGS_MAX_CONCURRENT_STREAMS(3) :最大流并发数,0代表不允许新建流,默认没有限制。
    • SETTINGS_INITIAL_WINDOW_SIZE(4):初始窗口大小,默认65535,不超过2 ^ 31-1。

(2)wireshark抓包

# 发送设置帧
202.89.233.101	192.168.1.46	HTTP2	123	SETTINGS[0], WINDOW_UPDATE[0]
Stream: SETTINGS, Stream ID: 0, Length 18
	Length: 18
	Type: SETTINGS (4)
	Flags: 0x00
		.... ...0 = ACK: False 
		0000 000. = Unused: 0x00
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0000 0000 = Stream Identifier: 0
	Settings - Header table size : 65536
	Settings - Max concurrent streams : 1000
	Settings - Initial Windows size : 6291456

# 发送设置帧确认	
192.168.1.46	202.89.233.101	HTTP2	92	SETTINGS[0]	
Stream: SETTINGS, Stream ID: 0, Length 0
	Length: 0
	Type: SETTINGS (4)
	Flags: 0x01
		.... ...1 = ACK: True
		0000 000. = Unused: 0x00
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0000 0000 = Stream Identifier: 0

4 WINDOW_UPDATE帧

(1)定义

img

  • 类型:0x8
  • 标志:无
  • 帧净荷:
    • Reserved:1位保留位
    • Window Size Increment:最大值位2^31-1

(2)wireshark抓包

Stream: WINDOW_UPDATE, Stream ID: 0, Length 4
	Length: 4
	Type: WINDOW_UPDATE (8)
	Flags: 0x00
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0000 0000 = Stream Identifier: 0
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 1111 0000 0000 0000 0001 = Window Size Increment: 983041

(3)补充

  • 流量控制是能作用某个流或整个连接(流标志符号为0,即根流可以限制依赖流)。
  • WINDOW_UPDATE可由一个已经发送带有END_STREAM标记的帧的对等端来发送。这意味着接收端可以在“半封闭(远程)”或者“关闭”的流上接收WINDOW_UPDATE帧。
  • 流量控制窗口用于指示发送端被允许传输的字节数(请回想起TCP的阻塞窗口和接受窗口)。
  • 流量控制计算不包含帧报头。
  • 流量窗口初始值为65535
  • 流量窗口为负值代表禁止发送
  • SETTING帧无法修改链接状态的流量控制窗口(即只能设置初始值,无法通过SETTING帧进行修改)
例如,如果客户端在建立的连接上立即发送60KB的数据,而终端将初始的窗口大小设置成16KB,客户端将重新计算流量控制窗口的可用空间为-44KB。终端将保持一个负数的流量控制窗口直到窗口更新帧恢复窗口到正数,这个时候客户端才能恢复数据发送。

5 PING帧

(1)定义

img

  • 长度:固定为0x8
  • 类型:0x6
  • ACK标志:位1用于标识0为请求,1为响应
  • 流标志符:固定为0x0
  • 帧净荷:ping的唯一标识符

(2)wireshark抓包

# 成对出现
192.168.1.46	202.89.233.100	HTTP2	100	PING[0]
Stream: PING, Stream ID: 0, Length 8
	Length: 8
	Type: PING (6)
	Flags: 0x00
		.... ...0 = ACK: False
		0000 000. = Unused: 0x00
   0... .... .... .... .... .... .... .... = Reserved: 0x0
   .000 0000 0000 0000 0000 0000 0000 0000 = Stream Identifier: 0
   Ping: 0000000000000001
   
   
202.89.233.100	192.168.1.46	HTTP2	100	PING[0]
Stream: PING, Stream ID: 0, Length 8
	Length: 8
	Type: PING (6)
	Flags: 0x00
		.... ...1 = ACK: True
		0000 000. = Unused: 0x00
   0... .... .... .... .... .... .... .... = Reserved: 0x0
   .000 0000 0000 0000 0000 0000 0000 0000 = Stream Identifier: 0
   Ping: 0000000000000001

6 RST_STREAM帧

(1)定义

img

  • 长度:固定为0x4
  • 类型:0x3
  • ACK标志:无
  • 流标志符:标识哪个流非正常终结
  • 帧净荷:错误码
    • NO_ERROR(0):没有错误,用于给GOWAY帧平滑关闭
    • PROTOCOL_ERROR(1):协议错误
    • INTERNAL_ERROR (2) : 终端遇到意外的内部错误。
    • FLOW_CONTROL_ERROR (3) : 终端检测到对等端违反了流量控制
    • SETTINGS_TIMEOUT (4) : 终端发送了设置帧,但没有及时收到响应。
    • STREAM_CLOSED (5) : 终端在流半封闭的时候收到帧。
    • FRAME_SIZE_ERROR (6) : 终端收到大小超过最大尺寸的帧(2^14 -1)。
    • REFUSED_STREAM (7) : 终端拒绝流在它执行任何应用处理之前.
    • CANCEL (8) : 终端使用这个标示某个流不再需要。
    • COMPRESSION_ERROR (9) : 终端无法维持报头压缩上下文的连接
    • CONNECT_ERROR (10) : 响应某个连接请求建立的连接被服为异常关闭。
    • ENHANCE_YOUR_CALM (11) : 终端检测出对等端在表现出可能会产生过大负荷的行为。
    • INADEQUATE_SECURITY (12) : 基础传输包含属性不满足文档或者终端申明的最小要求。

(2)wireshark抓包

Stream: RST_STREAM, Stream ID: 5, Length 4
	Length: 4
	Type: RST_STREAM (3)
	Flags: 0x00
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0000 0101 = Stream Identifier: 5
	Error: CANCEL (8)

7 PUSH_PROMISE

(1)定义

HTTP协议探究(六):H2帧详解和HTTP优化第7张

  • 长度:非固定
  • 类型:0x04
  • 标志:
    • END_HEADERS:位3标识帧包含了整个的报头块且后面没有延续帧。
    • Padded:位4标识Pad Length字段会呈现。
  • 流标志符(Stream Identifier)
  • 准备推送的流标志符(Promised-Stream-ID)
  • 首部块:HTTP首部

(2)wireshark抓包

# 由服务器建立流并发送HTTP头部
Stream: PUSH_PROMISE, Stream ID: 1, Length 166, GET /styles.780f923f35dd43d00653.css
	Length: 166
	Type: PUSH_PROMISE (5)
	Flags: 0x04
		.... .1.. = End Headers: True
		.... 0... = Padded: False
		0000 ..00 = Unused: 0x00
    0... .... .... .... .... .... .... .... = Reserved: 0x0
    .000 0000 0000 0000 0000 0000 0000 0001 = Stream Identifier: 1
    0... .... .... .... .... .... .... .... = Reserved: 0x0
    .000 0000 0000 0000 0000 0000 0000 0010 = Promised-Stream-ID: 2
    Header Block Fragment: 208244976109f54150bbaf0257c4ccacb7248d332000e36c...
    	Header: :method: GET
    	# ......

(3)补充

  • PUSH_PROMISE为服务器建立流,HEADERS为客户端建立流。
  • 服务器建立的流标识符为偶数(不包含0),0为根流标识符。
  • 客户端 -----HEADERS帧(含priority)-----> 服务器
  • 服务器 -----PUSH_PROMISE帧(不含priority)-----> 客户端,所以一般后续帧为 客户端 -----PRIORITY帧----> 服务器。

8 PRIORITY帧

(1)定义

HTTP协议探究(六):H2帧详解和HTTP优化第8张

  • 长度:非固定
  • 类型:0x02
  • 标志:无
  • 保留位和流标志符(Stream Identifier)
  • 独占位(Exclusive):1位,指示流的依赖是专有的
  • 依赖流标识符(Stream Dependency)
  • 优先级权重:1-256的权重值

(2)wireshark抓包

Stream: PRIORITY, Stream ID: 2, Length 5
	Length: 5
	Type: PRIORITY (2)
	Flags: 0x00
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0000 0010 = Stream Identifier: 2
	1... .... .... .... .... .... .... .... = Exclusive: True
	.000 0000 0000 0000 0000 0000 0000 0001 = Stream Dependency: 1
	Weight: 109

9 GOWAY帧

(1)定义

HTTP协议探究(六):H2帧详解和HTTP优化第9张

  • 长度:固定
  • 类型:0x07
  • 标志:无
  • 保留位和流标志符(Stream Identifier)
  • 保留位与最后一个流标识符
  • 错误码

(2)wireshark抓包

Stream: GOAWAY, Stream ID: 0, Length 8
	Length: 8
	Type: GOAWAY (7)
	Flags: 0x00
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0000 0000 = Stream Identifier: 0
	0... .... .... .... .... .... .... .... = Reserved: 0x0
	.000 0000 0000 0000 0000 0000 0000 0011 = Promised-Stream-ID: 3
	Error: NO_ERROR (0)

(3)补充

  • 通知远端对等端不要在这个连接上建立新流,即提示抛弃该连接,重新建立一条TCP连接。
  • 允许终端优雅的停止接收新的流,但仍可以继续完成之前已经建立的流的处理。

注:CONTINUTION帧省略,CONTINUTION帧比较简单。

三 Chrome插件解析HTTP2流量

88: HTTP2_SESSION
Start Time: 2018-12-03 14:36:45.975

# HEADERS帧
t= 10464 [st=     0]  HTTP2_SESSION_SEND_HEADERS
                      --> exclusive = true
                      --> fin = false
                      --> has_priority = true
                      --> :method: POST
                          :authority: cn.bing.com
                          :scheme: https
                          :path: /fd/ls/lsp.aspx
                          content-length: 1316
                          origin: https://cn.bing.com
                          user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36
                          content-type: text/xml
                          accept: */*
                          referer: https://cn.bing.com/
                          accept-encoding: gzip, deflate, br
                          accept-language: zh-CN,zh;q=0.9,en;q=0.8,en-US;q=0.7
                          cookie: _EDGE_V=1; MUID=1EF97277BD3961513FB57ECDBC17605A; MUIDB=1EF97277BD3961513FB57ECDBC17605A; SRCHD=AF=BEHPTB; SRCHUID=V=2&GUID=BD0C76F5F80546D8877C9F6688DDF1AA&dmnchg=1; ENSEARCH=BENVER=1; SRCHUSR=DOB=20181203&T=1543818612000; _EDGE_CD=u=zh-cn; _UR=MC=1; SRCHHPGUSR=CW=1536&CH=711&DPR=1.25&UTC=480&WTS=63679415390&NEWWND=1&NRSLT=-1&SRCHLANG=&AS=1&NNT=1&HAP=0; _EDGE_S=SID=04B092AF518367C83A3F9E1550AD6673; _SS=SID=04B092AF518367C83A3F9E1550AD6673&bIm=978208&HV=1543819002; ULC=P=1D5FE|9:1&H=1D5FE|5:1&T=1D5FE|6:1:8
                      --> parent_stream_id = 0
                      --> source_dependency = 259 (HTTP_STREAM_JOB)
                      --> stream_id = 25
                      --> weight = 220
# DATA帧                      
t= 10464 [st=     0]  HTTP2_SESSION_SEND_DATA
                      --> fin = true
                      --> size = 1316
                      --> stream_id = 25
# WINDOW_UPDATE帧                      
t= 10464 [st=     0]  HTTP2_SESSION_UPDATE_SEND_WINDOW
                      --> delta = -1316
                      --> window_size = 1047260
t= 10501 [st=    37]  HTTP2_SESSION_RECV_WINDOW_UPDATE
                      --> delta = 1316
                      --> stream_id = 0
t= 10501 [st=    37]  HTTP2_SESSION_UPDATE_SEND_WINDOW
                      --> delta = 1316
                      --> window_size = 1048576
                      
t= 10541 [st=    77]  HTTP2_SESSION_RECV_HEADERS
                      --> fin = false
                      --> :status: 204
                          x-msedge-ref: Ref A: D0007C217F0649D79ED88874FFB61759 Ref B: BJ1EDGE0217 Ref C: 2018-12-03T06:36:55Z
                          date: Mon, 03 Dec 2018 06:36:55 GMT
                      --> stream_id = 25
t= 10542 [st=    78]  HTTP2_SESSION_RECV_DATA
                      --> fin = true
                      --> size = 0
                      --> stream_id = 25
# PING帧                      
t= 96465 [st= 86001]  HTTP2_SESSION_PING
                      --> is_ack = false
                      --> type = "sent"
                      --> unique_id = 1
t= 96501 [st= 86037]  HTTP2_SESSION_PING
                      --> is_ack = true
                      --> type = "received"
                      --> unique_id = 1

# RST_STREAM
t=25836233 [st=1902]    HTTP2_SESSION_SEND_RST_STREAM
                        --> description = ""
                        --> error_code = "8 (CANCEL)"
                        --> stream_id = 5

t=222812 [st=212348]  HTTP2_SESSION_CLOSE
                      --> description = "Error 101 reading from socket."
                      --> net_error = -101 (ERR_CONNECTION_RESET)
t=222813 [st=212349]  HTTP2_SESSION_POOL_REMOVE_SESSION
t=222813 [st=212349] -HTTP2_SESSION

四 HTTP优化

(1)基于TCP和TLS优化后

注:HTTP协议探究(四):TCP和TLS优化

(2)减少DNS查询

  • 尽量不用多域名
  • 证书链不要太长

(3)减少HTTP重定向

  • HTTP 重定向极费时间,特别是不同域名之间的重定向,更加费时

(4)使用CDN(内容分发网络)

  • 把数据放到离用户地理位置更近的地方,可以显著减少每次TCP 连接的网络延
    迟,增大吞吐量。

(5)在客户端缓存资源

# nginx添加响应头
add_header Cache-Control private,max-age=86400,proxy-revalidate;

(6)传输压缩过的内容

  • 速度:brotli > gzip压缩 > 没压缩
# nginx使用ngx_brotli模块

# gzip压缩1.1,只有britli失效才有用
gzip  on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_types text/plain application/javascript application/x-javascript text/css application/xml text/javascript application/x-httpd-php image/jpeg image/gif image/png;
gzip_vary on;
gzip_disable "MSIE [1-6].";
gzip_comp_level         6;
gzip_http_version       1.1;

# brotli压缩所有HTTP版本
brotli on; 
brotli_comp_level 6; 
brotli_buffers 16 8k; 
brotli_min_length 20; 
brotli_types *; 

(7)消除不必要的请求开销

  • 升级HTTP2.0即可
  • HTTP2.0能够压缩头部,减少重复头部传输
# nginx配置
listen 443 ssl http2 fastopen=3 reuseport default_server;

(8)利用服务器推送

# nginx配置
location / {
    root   /home/nginx;
    index  index.html;
    http2_push /styles.389ab69b43b87e6d33f0.css;
    # ...
}

参考:

免责声明:文章转载自《HTTP协议探究(六):H2帧详解和HTTP优化》仅用于学习参考。如对内容有疑问,请及时联系本站处理。

上篇lua学习笔记10:lua简单的命令行bash 的环境配置文件下篇

宿迁高防,2C2G15M,22元/月;香港BGP,2C5G5M,25元/月 雨云优惠码:MjYwNzM=

相关文章

HTTP协议中GET请求方法中的请求头内容 : If-Modified-Since

问题背景 HTTP协议中GET请求方法中的请求头内容 : If-Modified-Since 具体描述 HTTP请求头的IMS(If-Modified-Since):浏览器缓存记录的该文件的最后服务器修改时间。 浏览器发送HTTP请求时,把If-Modified-Since一起发到服务器去,服务器会把这个时间与服务器上实际文件的最后修改时间进行比较。 如...

关于HTTP协议,一篇就够了

HTTP简介 HTTP协议是Hyper Text Transfer Protocol(超文本传输协议)的缩写,是用于从万维网(WWW:World Wide Web )服务器传输超文本到本地浏览器的传送协议。 HTTP是一个基于TCP/IP通信协议来传递数据(HTML 文件, 图片文件, 查询结果等)。 HTTP是一个属于应用层的面向对象的协议,由于其简捷...

【计算机网络】应用层

目录 网络应用模型 客户/服务器模型 P2P模型 域名系统(DNS) 层次域名空间 域名服务器 域名解析 文件传输协议(FTP) 工作原理 连接 电子邮件 电子邮件系统的组成结构 多用途网络邮件扩充(MIME) 简单邮件传输协议(SMTP) 邮局协议(POP3) 网际报文存取协议(IMAP) 基于万维网的电子邮件 万维网(WW...

07 | 自己动手,搭建HTTP实验环境

说明《透视HTTP协议》是 罗剑锋 (奇虎360技术专家)在极客时间开的一门专栏课,笔者记录一下学习笔记,仅供参考。 这一讲是“破冰篇”的最后一讲,我会先简单地回顾一下之前的内容,然后在 Windows 系统上实际操作,用几个应用软件搭建出一个“最小化”的 HTTP 实验环境,方便后续的“基础篇”“进阶篇”“安全篇”的学习。 “破冰篇”回顾 HTTP 协议...

关于HTTP协议头域详解

HTTP1.1  请求头:消息头   Accept:text/html,image/*  告诉服务器,客户机支持的数据类型 Accept-Charset:ISO-8859-1  告诉服务器,客户机采用的编码   Accept-EnCoding:gzip,compress 告诉服务器,客户机支持的数据压缩格式 Accept-Language:en   客户机...

WebSocket协议 8 问

WebSocket是一种比较新的协议,它是伴随着html5规范而生的,虽然还比较年轻,但大多主流浏览器都已经支持。它使用方面、应用广泛,已经渗透到前后端开发的各种场景中。 对http一问一答中二式流程的不满,催生了支持双向通信的WebSocket诞生。WebSocket是个不太干净协议。 一、WebSocket协议只能浏览器发起么? 不是。目前此协议的受...