HTTP2的优势:
- 服务端推送:不需要客户端解析html的时候再发送这些请求
- 头部压缩:节省消息头占用的网络流量
- 二进制传输:在协议的解析和优化扩展上带来更多的优势和可能
- 多路复用:所有的请求都是通过一个TCP连接,做到了真正的并发请求
概念:
服务器推送(server push)指的是,还没有收到浏览器的请求,服务器就把各种资源推送给浏览器。
举例:
比如,浏览器只请求了index.html,但是服务器把index.html、style.css、example.png全部发送给浏览器。这样的话,只需要一轮 HTTP 通信,浏览器就得到了全部资源,提高了性能。
实现方式:
nginx实现:
缺点:每次修改都要重启服务,而且应用与服务器的配置不应该混在一起
#nginx的配置文件 conf/conf.d/default.conf
# 如果用户请求根路径/,就推送style.css和example.png
server {
listen 443 ssl http2;
server_name localhost;
ssl on;
ssl_certificate /etc/nginx/certs/example.crt;
ssl_certificate_key /etc/nginx/certs/example.key;
ssl_session_timeout 5m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
http2_push /style.css;
http2_push /example.png;
}
}
后端实现
后端应用给服务器发送消息的时候,应该加上以下消息
Link: </styles.css>; rel=preload; as=style, </example.png>; rel=preload; as=image
php实现:
<?php
function pushImage($uri) {
header("Link: <{$uri}>; rel=preload; as=image", false);
return <<<HTML
<img src="{$uri}">
HTML;
}
$image1 = pushImage("/images/drucken.jpg");
$image2 = pushImage("/images/empire.jpg");
?>
<html>
<head><title>PHP Server Push</title></head>
<body>
<h1>PHP Server Push</h1>
<?php
echo ccbysa($image1, "https://bit.ly/1Wu5bYx",
"https://www.flickr.com/photos/hiperactivo/", "Javier Candeira");
echo ccbynd($image2, "https://bit.ly/24PHue3",
"https://www.flickr.com/photos/bobsfever/", "Robert McGoldrick");
?>
# 此时的nginx服务器配置
# 如果服务器或者浏览器不支持 HTTP/2,
# 那么浏览器就会按照 preload 来处理这个头信息,预加载指定的资源文件
server {
listen 443 ssl http2;
# ...
root /var/www/html;
location = / {
http2_push_preload on;
}
}
存在的问题:
所要推送的资源文件,如果浏览器已经有缓存,推送就是浪费带宽。即使推送的文件版本更新,浏览器也会优先使用本地缓存
解决方案:
只对第一次访问的用户开启服务器推送(根据cookie判断是否为第一次访问) ```nginx server { listen 443 ssl http2 default_server;
ssl_certificate ssl/certificate.pem; ssl_certificate_key ssl/key.pem;
root /var/www/html; http2_push_preload on;
location = /demo.html {
add_header Set-Cookie "session=1";
add_header Link $resources;
} }
map $http_cookie $resources { “~*session=1” “”; default “; as=style; rel=preload”; } ```