新的二进制格式(Binary Format),HTTP1.x的解析是基于文本。基于文本协议的格式解析存在天然缺陷,文本的表现形式有多样性,要做到健壮性考虑的场景必然很多,二进制则不同,只认0和1的组合。基于这种考虑HTTP2.0的协议解析决定采用二进制格式,实现方便且健壮。
多路复用(MultiPlexing),即连接共享,即每一个request都是是用作连接共享机制的。一个request对应一个id,这样一个连接上可以有多个request,每个连接的request可以随机的混杂在一起,接收方可以根据request的 id将request再归属到各自不同的服务端请求里面。
header压缩,如上文中所言,对前面提到过HTTP1.x的header带有大量信息,而且每次都要重复发送,HTTP2.0使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。
服务端推送(server push),同SPDY一样,HTTP2.0也具有server push功能。
为什么要用二进制流?
Http1.1:采用文本传输的,这样就会引发一个问题:所有的数据必须按顺序传输,比如需要传输:hello world,只能从h到d一个一个的传输,不能并行传输,因为接收端并不知道这些字符的顺序.
HTTP/2:引入二进制数据帧和流的概念,其中帧对数据进行顺序标识,如下图所示,这样浏览器收到数据之后,就可以按照序列对数据进行合并,而不会出现合并后数据错乱的情况。同样是因为有了序列,服务器就可以并行的传输数据,这就是流所做的事情。
HTTP1.1 :默认启用持久连接,持久连接对连接的性能提升巨大,但浏览器在一次请求发起后呆呆的等待服务器的相应却也不是办法。
然后大多数现代浏览器支持了主机打开6个连接,这意味着:
客户端可以并行分派最多6个请求;
服务器可以并行处理最多6个请求;
这样感觉浏览器可以欢快的加载网络资源了。但是这样的代价、成本却提高了,CPU 占用率提高了。
HTTP/2: 把消息分解为独立帧,交错发送,然后在另一端按照每个包重新组装,就实现了一个连接上有多个请求和响应,从而带来了巨大的性能提升,并行交错的发送请求、发送响应,请求之间、响应之间户不影响,一个连接可以并行发起多个请求和响应,消除不必要的延迟,从而减少页面加载时间
如果说http1.1要建立6个tcp连接,而http/2只需要1个在tomcat连接资源有限的情况下相当于节约了6倍的连接,在理论上性能达到的飞跃。
服务器推送(server push)指的是,还没有收到浏览器的请求,服务器就把各种资源推送给浏览器。
比如,浏览器只请求了index.html,但是服务器把index.html、style.css、example.png全部发送给浏览器。这样的话,只需要一轮 HTTP 通信,浏览器就得到了全部资源,提高了性能
本demo采用 jdk9,tomcat 9.0 springboot2.1.4
制作证书
使用JDK自带的keytool,证书类型为:PKCS12
-keystore 不会自动创建目录需要先手动建好.
keytool -genkey -alias undertow -storetype PKCS12 -keyalg RSA -keysize 2048 -keystore D:/keys/keystore.p12 -dname "CN=localhost, OU=localhost, O=localhost, L=ShangHai, ST=PUDONG, C=CN"
将D:\keys下生成的keystore.p12拷贝到src/main/resources下。然后在application.yml中配置服务器信息
server:
port: 8888 # 端口
compression:
enabled: true
http2:
enabled: true # 启用http2
ssl:
enabled: true
key-store: classpath:keystore.p12 # 启用http2
key-store-password: abc123 # 证书密码
key-store-type: PKCS12 # 证书类型
protocol: TLSv1.2 # 协议类型
key-alias: tomcat
spring:
application:
name: http2gateway
创建一个controller
@Controller
public class TestController {
@RequestMapping("/index2")
public String index2(Model map) {
List piclist = new ArrayList<String>();
for (int i = 0; i < 250; i++) {
piclist.add("pic" + i + ".jpg");
}
map.addAttribute("listmap", piclist);
return "/index2";
}
}
准备页面
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<body>
<ul th:each="lm : ${listmap}">
<li><img th:src="${lm}" /></li>
</ul>
</body>
</html>
请求https://localhost:8888/index2
protocol h2 代表我们请求采用的Http/2.0
我们请求下http1.1http://localhost:8082/Demo
可以看到Protocal是http1.1到这里我们实现了http/2.0Demo
我们测试加载250张图片来看一下http1.1 和http2.0的性能表现
http1.1
http2.0
通过测试可以看出http2.0加载250张图片比http1.1快出了3秒,3秒,3秒。还不赶快试试http2.0