http2

HTTP/1 HTTP/2 HTTP/3 对比分析

websocket和HTTP2.0的服务器推送有什么区别

http2.0需要客户端发起请求以后,进行相应,再附带推送,需要客户端发起请求。websocket不需要客户端发请求,就能实现推送。
http2.0的推送内容只是浏览器能够感知即存放在浏览器的缓存中,代码是无法获取到数据的,所以还得配合SSE获取数据。http2.0的推送内容典型场景:向后端请求一个html,服务器把html页面中的css,js等资源也推送到了浏览器,这是客户端发起请求时,直接在缓存中读取。websocket可以拿到数据,在代码中使用。
HTTP/2 连接不确定性会永远保持连接,而websocket有onclose事件,对代码友好。

HTTP2相较与HTTP1.1的优势

能够进行信道复用
分帧传输
每一帧都有一个上下文的联系
我们传输的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': '; 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': '; as=image; rel=preload'
Link头是HTTP2中指定推送内容的类型
这里推送的是/test.jpg,注意这里是访问路径
as用于指定类型,此处是图片
rel=preload 表示进行一个服务端的预推送

配置Nginx

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可以帮我们做这些兼容,开发者无需考虑

你可能感兴趣的:(javascript,前端,开发语言)