- 能够进行信道复用
- 分帧传输
- 每一帧都有一个上下文的联系
- 我们传输的HTTP请求的数据不一定要按照连续的顺序发送
- 分成不同的帧,然后一起进行发送
- 数据接收完成之后,根据帧信息的顺序进行组合
- 最后拿到完整的数据
- 因为分帧传输,可以在同一个链接上可以并发的发送不同的请求
- Server Push
- 在传统的HTTP协议中都是客户端主动,服务端被动
- 而在HTTP2中,可以让服务端变被动为主动
- 可以直接向客户端推送内容
- test.html
<img src="/test.jpg" alt="">
- server.js
const http = require('http') const fs = require('fs') http.createServer(function (req, res) { console.log('request come', req.url) const html = fs.readFileSync('test.html', 'utf8'); const img = fs.readFileSync('test.jpg'); if (req.url === '/') { res.writeHead(200, { 'Content-Type': 'text/html', 'Connection': 'keep-alive', 'Link': '</test.jpg>; as=image; rel=preload' }) res.end(html); } else { res.writeHead(200, { 'Content-Type': 'image/jpg', 'Connection': 'keep-alive' // or close }); res.end(img); } }).listen(8000, () => { console.log('server listening on 8000'); })
- 上述示例中
'Link': '</test.jpg>; as=image; rel=preload'
- Link头是HTTP2中指定推送内容的类型
- 这里推送的是/test.jpg,注意这里是访问路径
- as用于指定类型,此处是图片
- rel=preload 表示进行一个服务端的预推送
proxy_cache_path cache levels=1:2 keys_zone=my_cache:10m;
server {
listen 80;
listen [::]:80 default_server;
server_name test.com;
return 302 https://$server_name$request_uri;
location / {
proxy_cache my_cache;
proxy_pass http://127.0.0.1:8888;
proxy_set_header Host $host;
}
}
server {
listen 443 http2;
server_name test.com;
http2_push_preload on;
ssl on;
ssl_certificate_key ../certs/localhost-privkey.pem;
ssl_certificate ../certs/localhost-cert.pem;
location / {
proxy_cache my_cache;
proxy_pass http://127.0.0.1:8888;
proxy_set_header Host $host;
}
}
- 特别注意,针对我们的server_name,本机也要进行一些host的配置,此处不再赘述
- 现在的HTTP2基于HTTPS, 虽然在HTTP2的协议定义中没有指定一定要使用HTTPS
- 但是HTTP2是由谷歌开发的SPDY协议演化而来的, 而SPDY协议需要HTTPS
- 所以目前HTTP2只能在HTTPS的基础上使用
- 所以上述配置中
listen 443 http2
是规定的写法 http2_push_preload on;
是推送功能的开启
- 启动nginx和本地服务,访问我们的: https://test.com
- 可以在Network中看到,Protocol已经变成了h2
- 但是并没有看到是一个server push,而像是一个普通的请求
- 其原因是,我们目前所配置的HTTPS是不安全的,谷歌浏览器拒绝接受服务端推送
- 我们可以在 chrome://net-internnals/#http2 中看到网站使用了http2 push的功能
- 显示Pushed有1条,Pushed and claimed有0条,意味着有1条推送,但并没有被浏览器接收
- 浏览器在展示的时候把Pushed数据伪装成了普通请求的样子
- 扩展:https://http2.akamai.com/demo/http2-lab.html
- 可通过上面的网站来测试HTTP2的性能
- HTTP2相较于HTTP1.1的性能有本质的提升,同时HTTP2开启了Server Push又提高了不少
- 其整体性能提升不体现在Server Push上,而是体现在信道复用和分帧传输的设计上
- 因为有了上述的设计,我们可以通过一个TCP链接进行并发就行了
- 因为不是所有的浏览器都支持HTTP2,有时候我们需要回退到HTTP1.1
- 如果使用Nginx来开启HTTP2, 它会帮我们进行一个兼容,这个兼容方案是:ALPN
- 客户端和服务端进行协商到底使用哪个协议
- 可以测试:$
curl -v https://test.com
- 可以看到提示信息:
ALPN, offering h2, ALPN, offering http/1.1
- 可以看到提示信息:
- 我们直接使用 $
curl -v -k https://test.com
- 可以看到提示信息:
ALPN, server accepted to use h2
- 这表示客户端如果支持h2, 服务端就会使用h2进行传输
- 可以看到提示信息:
- 如果我们想使用http1.1访问: $
curl -v -k --http1.1 https://test.com
- 可以看到
ALPN, server accepted to use http/1.1
- 可以看到
- 我们在做开发的时候,直接使用HTTP1.1标准开发就行了,因为服务端一般不直接从客户端接收数据
- Nginx可以帮我们做这些兼容,开发者无需考虑