深入浅出:HTTP/2

上篇文章深入浅出:5G和HTTP里给自己挖了一根深坑,说是要写一篇关于HTTP/2的文章,今天来还账了。

本文分为以下几个部分:

  1. HTTP/2的背景
  2. HTTP/2的特点
  3. HTTP/2的协议分析
  4. HTTP/2的支持 

HTTP/2简介

HTTP/2主要是为了解决现HTTP 1.1性能不好的问题才出现的。当初Google为了提高HTTP性能,做出了SPDY,它就是HTTP/2的前身,后来也发展成为HTTP/2的标准。

HTTP/2兼容HTTP 1.1,例如HTTP Method,Status code,URI以及大部分Header Fields。

HTTP/2通过以下方法减少latency,用来改进页面加载的速度,

  1. HTTP Header的压缩,采用的是HPack算法。
  2. HTTP/2的Server Push,非常重要的一个特性。
  3. 请求的pipeline。
  4. 修复在HTTP 1.x的队头阻塞问题。
  5. 在单个TCP连接里多工复用请求。

HTTP/2支持HTTP 1.1里的大部分use case,例如桌面浏览器、移动浏览器、Web API、Web Server、代理服务器、反向代理服务器、防火墙和CDN等。

HTTP/2 头部压缩(HPack)

HPack是HTTP/2 里HTTP头压缩的算法,具体可以参看https://tools.ietf.org/html/rfc7541。下面简单介绍一下HPack是如何工作的。

见下图,该图来自Google 的性能专家 Ilya Grigorik 的文章HTTP/2 is here, let's optimize!,它非常直观地描述了 HTTP/2 中头部压缩的原理:

简单说,HTTP头压缩需要在HTTP/2 Client和服务端之间:

  • 维护一份相同的静态表(Static Table),包含常见的头部名称,以及特别常见的头部名称与值的组合;
  • 维护一份相同的动态表(Dynamic Table),可以动态地添加内容;
  • 基于静态哈夫曼码表的哈夫曼编码(Huffman Coding);

在HTTP头里,有些key:value是固定,例如:

 :method: GET:scheme: http

在编码时,它们直接用一个index编号代替,例如:method:GET是2,这些在一个静态表定义。静态表的定义如下,总共61个Header Name,点击URL https://tools.ietf.org/html/rfc7541#appendix-A查看所有静态表的定义。

 

IndexHeader NameHeader Value
1:authority 
2:methodGET
3:methodPOST
4:path/
5:path/index.html
6:schemehttp
7:schemehttps
8:status200
.........
32cookie 
.........
60via 
61www-authenticate 

 

使用静态表、动态表、以及Huffman编码可以极大地提升压缩效果。对于静态表里的字段,原来需要N个字符表示的,现在只需要一个索引即可,对于静态、动态表中不存在的内容,还可以使用哈夫曼编码来减小体积。HTTP/2 标准里也给出了一份详细的静态哈夫曼码表(https://tools.ietf.org/html/rfc7541#appendix-B),它们需要内置在客户端和服务端之中。

关于HPack的算法和实现,后面专门抽一篇文章来写。

HTTP/2 ALPN

HTTP/2协议里有个negotiation的机制,让客户端和服务器选择使用HTTP 1.1还是2.0,这个是由ALPN来实现,关于ALPN,可以参看

ALPN(Transport Layer Security (TLS) Application-Layer Protocol Negotiation Extension,https://tools.ietf.org/html/rfc7301。 

下面是抓包截图,在TLS里的Client Hello的包里,我们可以看到ALPN里由H2和HTTP/1.1,这就是说客户端支持HTTP2以及HTTP 1.1.

当Server收到后,会识别Client发过来的协议列表,如果不认识就忽略掉。如果认识多个,则选择一个最合适的协议发布给Client。也是在Server Hello里的ALPN返回,见下图。

HTTP/2 Server Push机制

Server Push是HTTP 2最重要的一个特性。

在HTTP 1.1里,在同一个 TCP 连接里面,上一个回应(response)发送完了,服务器才能发送下一个,但在HTTP/2里,可以将多个回应一起发送。

下图是PUSH模式,当请求一个HTML时,如果HTML里有CSS文件,server会一并推给client,而不像在HTTP 1.1下,还需要再发一个CSS的请求。

根据上图,从理论上PUSH模式下性能会好很多。

举个例子解释一下。下面是一个简单的HTML页面,假说是index.html 。

<html>
<head><link rel="stylesheet" href="style.css">
</head>
<body><p>This is a sample to illustrate how HTTP/2 works</p><img src="example.png">
</body>
</html>

这里有三个文件需要处理:该HTML页面、CSS文件style.css以及图片example.png。在HTTP 1.1里为了处理这三个文件,Client需要发三个请求给Server。

首先,发送一个请求index.html,

GET /index.html HTTP/1.1

Client解析该HTML文件,继而知道有2个style.css和example.png资源文件下载。

Client继续发送2个请求下载他们。

GET /style.css  HTTP/1.1

以及

GET /example.png  HTTP/1.1

一般为了解决这两个问题,像CSS文件,可以把CSS code直接放在HTML里,也可以把example.png转化为base64 code嵌入在HTML里,以上只是把外部资源文件合并到HTML里。

除了上述方法,还有一个优化的方法,就是Preload(预加载),可以参看这里,https://w3c.github.io/preload/。 

所以我们可以把HTML代码改成如下:

<link rel="preload" href="/styles.css" as="style">
<link rel="preload" href="/example.png" as="image">

那Preload是什么意思呢?就是说下载前一个页面时,可以把相关的资源文件预先加载好,这样感觉起来会快一些。但是有一个关键问题需要注意,即便是预加载的情况下,也不能减少HTTP请求次数。 

针对上面的问题,我们引出服务器推送(server push)。根据上面的图,我们可以看出,Server还没有收到Client的请求,就把各种资源推送给Client。

拿上面例子继续举例,当Client只请求index.html,但是Server把index.htmlstyle.cssexample.png全部发送给浏览器。这样只需要一轮 HTTP 通信,Client就得到了全部资源。

 

HTTP/2的支持

现在主流的软件都支持HTTP/2.

浏览器

基本上大部分浏览器在2015年底都支持HTTP/2了,包括Chrome、Opera、Firefox、IE 11、Safari,Edge。

在Chrome上,可以下载插件HTTP Indicator,判断访问的网站是否支持HTTP/2.

也可以打开Chrome的开发者工具,打开Network tab,可以看到Protocol为h2的就是HTTP/2请求。如果Initiator为push的,说明开启了Server Push模式。

 

常用Server软件

  1. Apache HTTPd,从版本2.4.12开始支持,通过模块mod_h2来支撑。
  2. Apache Tomcat,从版本8.5开始支持。
  3. Jetty从9.3开始支持。
  4. Netty从4.1开始。
  5. IIS在Win10和WIndows Server 2016支持。
  6. Ngnix从1.9.5开始支持HTTP2,但Server Push功能则在1.13.9才开始。

硬件

  1. Ctrix NetScaler从11.x开始支持
  2. F5 BIG-IP从11.6开始。

CDN/Cloud

  1. Akamai
  2. AWS
  3. Azure
  4. Aliyun
  5. Tecent Cloud

缓存问题

如果开启了Server Push模式,我们很容易意识到一个问题,那就是缓存问题。Server见到HTML页面就把外部资源push给Client,如果没有缓存,其实很浪费。为了解决这个问题,可以在第一次请求时push,后面的请求都不push了。

服务器推送有一个很麻烦的问题。所要推送的资源文件,如果浏览器已经有缓存,推送就是浪费带宽。即使推送的文件版本更新,浏览器也会优先使用本地缓存。下面是 Nginx 官方给出的示例,根据 Cookie 判断是否为第一次访问(https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/)。

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 "</style.css>; as=style; rel=preload, </image1.jpg>; as=image; rel=preload, </image2.jpg>; as=image; rel=preload";

HTTP/2的性能

有人专门做过测试,https://www.smashingmagazine.com/2017/04/guide-http2-server-push/#measuring-server-push-performance,借用该文的一张图片,

可以看出,启用HTTP/2后性能并未大幅度提升,所以在使用HTTP/2还是谨慎一些,如果使用不当,反而会使性能下降。

另外,Ngnix专门撰文描述7个提高HTTP/2的技巧https://www.nginx.com/blog/7-tips-for-faster-http2-performance/ 。

参考文章:

  1. https://en.wikipedia.org/wiki/HTTP/2
  2. https://tools.ietf.org/html/rfc7301
  3. https://tools.ietf.org/html/rfc7541 (HPack)
  4. http://www.ruanyifeng.com/blog/2018/03/http2_server_push.html
  5. https://www.nginx.com/blog/nginx-1-13-9-http2-server-push/
  6. https://www.smashingmagazine.com/2017/04/guide-http2-server-push/#measuring-server-push-performance
  7. https://www.nginx.com/blog/7-tips-for-faster-http2-performance/ 
  8. https://w3c.github.io/preload/
  9. http://velocityconf.com/devops-web-performance-2015/public/schedule/detail/42385

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/388798.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

画了个Android

画了个Android 今晚瞎折腾&#xff0c;闲着没事画了个机器人——android&#xff0c;浪费了一个晚上的时间。画这丫还真不容易&#xff0c;为那些坐标&#xff0c;差点砸了键盘&#xff0c;好在最后画出个有模有样的&#xff0c;心稍安。 下面来看看画这么个机器人需要些什么东…

数据治理 主数据 元数据_我们对数据治理的误解

数据治理 主数据 元数据Data governance is top of mind for many of my customers, particularly in light of GDPR, CCPA, COVID-19, and any number of other acronyms that speak to the increasing importance of data management when it comes to protecting user data.…

mysql 选择前4个_mysql从4个表中选择

不要认为GROUP BY是必需的 . 虽然如果一个孩子有2个父记录&#xff0c;你可能想用它来将2个父母分组到一行 - 但不确定这是否是你的要求 . 因为如果一个孩子有2个父母&#xff0c;那么将为该孩子返回的父母是未定义的 .假设所有孩子都有父母&#xff0c;所有父母都会有姓&#…

提高机器学习质量的想法_如何提高机器学习的数据质量?

提高机器学习质量的想法The ultimate goal of every data scientist or Machine Learning evangelist is to create a better model with higher predictive accuracy. However, in the pursuit of fine-tuning hyperparameters or improving modeling algorithms, data might …

mysql 集群实践_MySQL Cluster集群探索与实践

MySQL集群是一种在无共享架构(SNA&#xff0c;Share Nothing Architecture)系统里应用内存数据库集群的技术。这种无共享的架构可以使得系统使用低廉的硬件获取高的可扩展性。MySQL集群是一种分布式设计&#xff0c;目标是要达到没有任何单点故障点。因此&#xff0c;任何组成部…

Python基础:搭建开发环境(1)

1.Python语言简介 2.Python环境 Python环境产品存在多个。 2.1 CPython CPython是Python官方提供的。一般情况下提到的Python就是指CPython&#xff0c;CPython是基于C语言编写的。 CPython实现的解释器将源代码编译为字节码&#xff08;ByteCode&#xff09;&#xff0c;再由虚…

python数据结构之队列(一)

队列概念队列&#xff08;queue&#xff09;是只允许在一端进行插入操作&#xff0c;而在另一端进行删除操作的线性表。队列是一种先进先出的&#xff08;First In First Out&#xff09;的线性表&#xff0c;简称FIFO。允许插入的一端为队尾&#xff0c;允许删除的一端为队头。…

Android实现图片放大缩小

Android实现图片放大缩小 package com.min.Test_Gallery; import Android.app.Activity; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.Color; import android.graphics.Matrix; import android.os.Bun…

matlab散点图折线图_什么是散点图以及何时使用

matlab散点图折线图When you were learning algebra back in high school, you might not have realized that one day you would need to create a scatter plot to demonstrate real-world results.当您在高中学习代数时&#xff0c;您可能没有意识到有一天需要创建一个散点图…

java判断题_【Java判断题】请大神们进来看下、这些判断题你都知道多少~

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼、判断改错题(每题2分&#xff0c;共20分)(正确的打√&#xff0c;错误的打并说明原因)1、 Java系统包提供了很多预定义类,我们可以直接引用它们而不必从头开始编写程序。 ( )2、 程序可以用字符‘*’替代一个TextField中的每个字…

PoPo数据可视化第8期

PoPo数据可视化 聚焦于Web数据可视化与可视化交互领域&#xff0c;发现可视化领域有意思的内容。不想错过可视化领域的精彩内容, 就快快关注我们吧 :) 微信订阅号&#xff1a;popodv_com谷歌决定关闭云可视化服务 Fusion Tables谷歌宣布即将关闭其 Fusion Tables 云服务&#x…

AC自动机题单

AC自动机题目 真的超级感谢xzy 真的帮到我很多 题单 [X] [luogu3808]【模板】AC自动机&#xff08;简单版&#xff09; https://www.luogu.org/problemnew/show/P3808[X] [luogu3796]【模板】AC自动机&#xff08;加强版&#xff09;https://www.luogu.org/problemnew/show/P37…

java list用法_Java List 用法详解及实例分析

Java List 用法详解及实例分析Java中可变数组的原理就是不断的创建新的数组&#xff0c;将原数组加到新的数组中,下文对Java List用法做了详解。List:元素是有序的(怎么存的就怎么取出来&#xff0c;顺序不会乱)&#xff0c;元素可以重复(角标1上有个3&#xff0c;角标2上也可以…

python字符串和List:索引值以 0 为开始值,-1 为从末尾的开始位置;值和位置的区别哦...

String&#xff08;字符串&#xff09;Python中的字符串用单引号 或双引号 " 括起来&#xff0c;同时使用反斜杠 \ 转义特殊字符。 字符串的截取的语法格式如下&#xff1a; 变量[头下标:尾下标]索引值以 0 为开始值&#xff0c;-1 为从末尾的开始位置。[一个是值&#x…

逻辑回归 python_深入研究Python的逻辑回归

逻辑回归 pythonClassification techniques are an essential part of machine learning and data science applications. Approximately 70% of problems in machine learning are classification problems. There are lots of classification problems that are available, b…

spring定时任务(@Scheduled注解)

&#xff08;一&#xff09;在xml里加入task的命名空间 xmlns:task"http://www.springframework.org/schema/task" http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-4.1.xsd&#xff08;二&#xff09;启用注…

net user 用户名 密码 /add 建立用户

net user 用户名 密码 /add 建立用户 other: net use \\ip\ipc$ " " /user:" " 建立IPC空链接 net use \\ip\ipc$ "密码" /user:"用户名" 建立IPC非空链接 net use h: \\ip\c$ "密码" /user:"用户名" 直接登陆后映…

JavaScript是如何工作的:与WebAssembly比较及其使用场景

*摘要&#xff1a;** WebAssembly未来可期。 原文&#xff1a;JavaScript是如何工作的&#xff1a;与WebAssembly比较及其使用场景作者&#xff1a;前端小智Fundebug经授权转载&#xff0c;版权归原作者所有。 这是专门探索 JavaScript及其所构建的组件的系列文章的第6篇。 如果…

友元 java_C++ 友元关系详解

在C中&#xff0c;在某些情况下&#xff0c;允许特定的非成员函数访问一个类的私有成员&#xff0c;同时仍然阻止一般的访问&#xff0c;这是很方便做到的。例如&#xff0c;被重载的操作符&#xff0c;如输入或输出操作符&#xff0c;经常需要访问类的私有数据成员。这些操作符…

Matplotlib中的“ plt”和“ ax”到底是什么?

Indeed, as the most popular and fundamental data visualisation library, Matplotlib is kind of confusing in some perspectives. It is usually to see that someone asking about的确&#xff0c;作为最受欢迎的基础数据可视化库&#xff0c;Matplotlib在某些方面令人困…