HTTP2的优势:

  • 服务端推送:不需要客户端解析html的时候再发送这些请求
  • 头部压缩:节省消息头占用的网络流量
  • 二进制传输:在协议的解析和优化扩展上带来更多的优势和可能
  • 多路复用:所有的请求都是通过一个TCP连接,做到了真正的并发请求

概念:

服务器推送(server push)指的是,还没有收到浏览器的请求,服务器就把各种资源推送给浏览器。

举例:

比如,浏览器只请求了index.html,但是服务器把index.html、style.css、example.png全部发送给浏览器。这样的话,只需要一轮 HTTP 通信,浏览器就得到了全部资源,提高了性能。

实现方式:

nginx实现:

  • 缺点:每次修改都要重启服务,而且应用与服务器的配置不应该混在一起

    1. #nginx的配置文件 conf/conf.d/default.conf
    2. # 如果用户请求根路径/,就推送style.css和example.png
    3. server {
    4. listen 443 ssl http2;
    5. server_name localhost;
    6. ssl on;
    7. ssl_certificate /etc/nginx/certs/example.crt;
    8. ssl_certificate_key /etc/nginx/certs/example.key;
    9. ssl_session_timeout 5m;
    10. ssl_ciphers HIGH:!aNULL:!MD5;
    11. ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2;
    12. ssl_prefer_server_ciphers on;
    13. location / {
    14. root /usr/share/nginx/html;
    15. index index.html index.htm;
    16. http2_push /style.css;
    17. http2_push /example.png;
    18. }
    19. }

    后端实现

    后端应用给服务器发送消息的时候,应该加上以下消息

    1. Link: </styles.css>; rel=preload; as=style, </example.png>; rel=preload; as=image

    php实现:

    1. <?php
    2. function pushImage($uri) {
    3. header("Link: <{$uri}>; rel=preload; as=image", false);
    4. return <<<HTML
    5. <img src="{$uri}">
    6. HTML;
    7. }
    8. $image1 = pushImage("/images/drucken.jpg");
    9. $image2 = pushImage("/images/empire.jpg");
    10. ?>
    11. <html>
    12. <head><title>PHP Server Push</title></head>
    13. <body>
    14. <h1>PHP Server Push</h1>
    15. <?php
    16. echo ccbysa($image1, "https://bit.ly/1Wu5bYx",
    17. "https://www.flickr.com/photos/hiperactivo/", "Javier Candeira");
    18. echo ccbynd($image2, "https://bit.ly/24PHue3",
    19. "https://www.flickr.com/photos/bobsfever/", "Robert McGoldrick");
    20. ?>
    1. # 此时的nginx服务器配置
    2. # 如果服务器或者浏览器不支持 HTTP/2,
    3. # 那么浏览器就会按照 preload 来处理这个头信息,预加载指定的资源文件
    4. server {
    5. listen 443 ssl http2;
    6. # ...
    7. root /var/www/html;
    8. location = / {
    9. http2_push_preload on;
    10. }
    11. }

    存在的问题:

    所要推送的资源文件,如果浏览器已经有缓存,推送就是浪费带宽。即使推送的文件版本更新,浏览器也会优先使用本地缓存

解决方案:

  1. 只对第一次访问的用户开启服务器推送(根据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 {

    1. add_header Set-Cookie "session=1";
    2. add_header Link $resources;

    } }

map $http_cookie $resources { “~*session=1” “”; default “; as=style; rel=preload”; } ```