http请求丢部分数据_温故知新,HTTP/2

去年年底,据国际互联网工程任务组( IETF )消息,HTTP-over-QUIC 实验性协议将被重命名为 HTTP/3,即有望成为 HTTP 协议的第三个正式版本,也就是说HTTP/3可能要来了。 该消息是如此的惹人注目,是因为HTTP是我们身边的协议,Web应用都离不开它。 

212e90e9948e0998b73e743ee81645fe.png

温故知新,梳理一下过往,或许更能够理解未来。

HTTP1.x的过往

HTTP协议大约诞生在我上大一的时候,好像是HTTP0.9,客户端请求和服务器响应都是ascii码,客户端以回车符结尾,服务器返回HTML。后来的HTTP1.0,服务器响应增加了很多状态,请求和响应也多了很多的header,响应的内容也不再局限于纯文本了。

b72cea4079f0b44ab580953621c47b56.png

HTTP是一个应用层协议,由请求和响应构成,是一个标准的客户端服务器模型,是一个无状态的协议。HTTP是建立在TCP之上的,每个请求都要经历三次握手和慢启动。客户端是依据域名来向服务器建立连接,一般PC端的浏览器支持同域6~8个连接,手机端的连接数则一般控制在4~6个。连接数不是越多越好,资源开销和整体延迟都会随之增大。

HTTP 1.1 导致了2000年的互联网热潮。HTTP1.1 支持只发送header信息(不带任何body信息),如果服务器认为客户端有权限请求服务器,则返回100,否则返回401。客户端如果接受到100,才开始把请求body发送到服务器。这样当服务器返回401的时候,客户端就可以不用发送请求body了,节约了带宽。

7a07c66403c40d8b3d34b7361b771875.png

另外HTTP还支持传送内容的一部分。这样当客户端已经有一部分的资源后,只需要跟服务器请求另外的部分资源即可。RANGE:bytes是HTTP/1.1新增内容,HTTP/1.0每次传送文件都是从文件头开始,即0字节处开始。RANGE:bytes=XXX表示要求服务器从文件XXX字节处开始传送,这大概就是平时所说的断点续传。

相关的部分协议标准如下:

协议编号 协议名称简要描述
RFC7230 HTTP/1.1: Message Syntax and Routing底层消息解析和连接管理等
RFC7231HTTP/1.1: Semantics and Content方法、状态码和header等
RFC7232HTTP/1.1: Conditional Requests例如If-Modified-Since
RFC7233HTTP/1.1: Range Requests获取部分内容等
RFC7234HTTP/1.1: Caching浏览器和中介缓存等
RFC7235HTTP/1.1: AuthenticationHTTP 的一个authentication框架等

现如今,Web应用不再单纯是web 网页,还有支持多设备和多媒体。 一个SPA的应用可能有上百的连接,模块拆分导致了更多的请求,大部分时间都消耗在网络上。HTTP 1.x header 往往较大,且无法压缩。TCP协议利用过低,不可复用连接,连接数限制且协议过于庞大。

4cb4b95524c8b702b97a6d3f3bf4c4c9.png

HTTP1.x遇到的问题和解决方案

HTTP1.x主要存在连接无法复用和head of line blocking这两个问题。在第一个请求没有收到回复之前,后续从应用层发出的请求只能排队。网络通畅的时候性能影响不大,一旦第一个请求没有抵达服务器,或者response因为网络阻塞没有及时返回,就会影响所有后续请求。

HTTP1.0协议头里可以设置Connection:Keep-Alive。在header里设置Keep-Alive可以在一定时间内复用连接,具体复用时间的长短可以由服务器控制,一般在15秒左右,这与运营商蜂窝网络的linger time相关。HTTP1.1之后Connection的默认值就是Keep-Alive,如果要关闭连接复用需要显式的设置Connection:Close。这对PC端浏览器的体验帮助很大,因为大部分的请求在集中在一小段时间以内。但移动app的请求比较分散且时间跨度相对较大,一般会从应用层寻求其它解决方案,长连接方案或者伪长连接方案。

67a6f62b7de9566fc669188245c15e1a.png

为了解决HTTP连接复用,可以采用长轮询,HTTP streaming和websocket等方式。

和传统的HTTP短链接相比,长连接轮询会在用户增长的时候极大的增加服务器压力。移动端网络环境复杂,像wifi和4g的网络切换等,这些场景都需要考虑重建连接。长轮询方式稳定性并不好,需要做好数据可靠性的保证,比如重发和ack机制。而且,response有可能会被中间代理cache住,要处理好业务数据的过期机制。

HTTP streaming是通过在server response的头部里增加"Transfer Encoding: chunked"来告诉客户端后续还会有新的数据。如果永远不会结束,客户端就会一直处于等待response的过程中。代理服务器会等待服务器的response结束之后才会将结果推送到请求客户端。对于streaming这种业务数据无法按照请求来做分割,所以客户端每收到一块数据都需要自己做协议解析。显然这个数据通道也是单向的,还有个缺陷就是不会产生重复的header数据。

websocket提供双向的数据通道,优势在于提供了message的概念,比基于字节流的tcp socket使用更简单,同时又提供了传统的HTTP所缺少的长连接功能。但代价相对较高,基于tcp的socket编程技术难度相对复杂很多,而且需要自己制定协议。

HTTP/2 要点

HTTP2.0是以SPDY为原型进行讨论和标准化的,采用二进制格式传输数据,而非 HTTP/1.x 的文本格式。请求和响应都统一为流,对消息头采用 HPACK 进行压缩传输,能够节省消息头占用的网络的流量。多路复用,就是所有的请求都是通过一个 TCP 连接并发完成,并支持Server Push和基于优先级的流量控制。

fa18540e78a99b9ab92123453a766ae5.png

HTTP/2 中的帧

帧(frame)是HTTP2中最小的通信单位,每个帧都会有帧header,每个帧用来承载HTTP header 或负荷数据,或其他特定类型的帧。帧是遵循二进制编码的。帧格式如下:

f6d63592f12f34a1e604340904ebff00.png

length定义了整个帧的长度,type定义帧主要有10种的类型:

帧类型code
DATA0x0
HEADERS0x1
PRIORITY0x2
RSTSTREAM0x3
PUSHPROMISE0x4
SETTINGS0x5
PING0x6
GOAWAY0x7
WINDOW_UPDATE0x8
CONTINUATION0x9

flags用位定义了一些重要的参数,stream id用作流控制,而payload才是请求的正文。

虽然协议的格式和HTTP1.x完全不同了,但并没有改变HTTP1.x的语义,只是把原来HTTP1.x的header和body部分用frame重新封装了一层而已。调试的时候浏览器甚至会把HTTP2.0的frame自动还原成HTTP1.x的格式。HTTP2.0与HTTP1.0的对比如下:

6c800f2fb8cd7fbb313a5b24e4d2fd7b.png

HTTP/2 中的header 压缩

HTTP1.x的header由于cookie和user agent很容易变得较大,而且每次都要重复发送。HTTP/2使用encoder来减少需要传输的header大小,通讯双方各自cache一份header fields表,既避免了重复header的传输,又减小了需要传输的大小。高效的压缩算法可以很大的压缩header,减少发送包的数量从而降低延迟。

d436eb64fc356ec62d13de2984e6c5d6.png

HTTP/2中的HPACK使用一份索引表来定义常用的 HTTP Header,保留原有的header list的顺序,通过索引键值压缩。 静态表中包含了一些预定义的header字段,动态表默认是空的,会在头部解压缩的时候确定是否添加entry。客户端和服务器端使用header表来跟踪和存储之前发送的每一个键值对。在tcp连接期间,二者共同维护和更新。对于无法用索引替代的字符,有的会采用哈夫曼编码压缩。

ed613bbf26dd70a9fdcd9e2474886513.png

HTTP/2 中的多路复用

把HTTP 消息分解为独立的帧,交错发送,然后在另一端根据Stream ID 重新组装是HTTP 2.0 最重要的一项增强。每个 Frame Header 都有一个 Stream ID。每次请求/响应使用不同的 Stream ID。通过 Stream ID 标识,所有的请求和响应都可以同时跑在一个TCP 连接上了。 下图是 HTTP 和 spdy的并发模型对比:

6fd22c0bc64451da421ac02fc16ec294.png

和一般TCP连接释放一样,如果客户端没有数据要请求,或服务端数据发送完毕后,会主动发送关闭连接的报文。或者是服务端连续发送探测报文,客户端无响应,服务端就关闭了这个连接。

当流并发时,就会涉及到流的优先级和依赖。优先级高的流会被优先发送。每个HTTP/2流里面可以带有优先级(31位,0为优先级最高)的值,这个值确定着客户端和服务器处理不同的流采取不同的优先级策略,高优先级的流都应该优先发送。图片请求的优先级要低于CSS和SCRIPT脚本,这可以确保重要的东西可以被优先加载。,但又不会绝对的,绝对地遵守可能又会引入队列阻塞的问题:高优先级的请求慢导致阻塞其他资源交付。

从tcp连接和网络来看,优先级使得网络拥塞得到改善,慢启动时间减少,拥塞和丢包恢复速度变快。

HTTP/2 中的Push

Server Push 就是服务器向客户端推送资源而无需客户端明确地请求,或者服务器可以对一个客户端请求发送多个响应。

852bdc79aa7adcf6d6e3b234863703a4.png

当服务端需要主动推送某个资源时,便会发送一个 Frame Type 为 PUSH_PROMISE 的 帧,里面带了 PUSH 需要新建的 Stream ID。客户端解析 帧时,发现它是一个 PUSH_PROMISE 类型,便会准备接收服务端要推送的流。

HTTP/2连接建立后,客户端与服务器交换SETTINGS 帧,以此来限定双向并发流的最大数量。因此,客户端可以限定推送流的数量,或者通过把这个值设置为0,完全禁用服务器推送,而且,所有推送的资源都遵守同源策略。服务器不能随便将第三方资源推送给客户端,而必须是经过双方确认才行。

所有服务器推送流都由PUSH_PROMISE 发起,PUSH_PROMISE 帧必须在返回响应之前发送,以免客户端出现竞态条件。客户端接收到PUSH_PROMISE 帧之后,可以视自身需求选择拒绝这个流。

a225340bd4fa962935cd7029a6b2b926.png

基于HTTP/2的开发

HTTP/2 已经得到了较为广泛的支持,服务器的支持包括:

  • Apache HTTP Server 2.4.17+ 

  • Apache Tomcat 8.5+

  • NGINX 1.9.5+

  • 面向PHP的Swoole

  • 面向Python 的Twisted

  • ...

支持HTTP/2的客户端包括:

  • Chromium 

  • Mozilla Firefox

  • curl and libcurl

  • OkHTTP (java ,Android)

  • 面向Obj-C/swift 的 WKWebView

  • ...

客户端与服务器同时支持HTTP/2的包括:

  • Jetty/Netty

  • lua-HTTP

  • Node.js 8.4.0+

  • 面向perl 的 Protocol::HTTP2

  • 面向Go 的HTTP2

  • ...

支持HTTP/2的代理中介包括:

  • HAProxy

  • ngHTTP2

  • GFE

  • ...

详情可以参考HTTPs://github.com/HTTP2/HTTP2-spec/wiki/Implementations。

调试工具可以使用chrome的浏览器以及Wireshark等等。

7206a989b28fbc68c397c60a2f1dc02e.png

在开发中使用了HTTP/2 并不是万事大吉了,在HTTP1.X 中的一些优化还需要继续使用,例如减少DNS查询和重定向,CDN的使用,对代码、图片等资源的压缩,对文本开启GZip,以及使用HTTP的缓存机制(Expires/Cache-Control和Last-Modified / ETag)等等。对于那些可以感知缓存的资源内联或者Push 消息,可以利用cookie 协助用户标记。

由于HTTP/2基于单个TCP连接,容易受到 Head of Line Blocking 的影响,从而导致传输速度受限,还会受到TCP丢包的影响,所以HTTP/2在资源数量较少的网站可能效果不明显。TCP协议的升级依赖于操作系统内核的升级,尤其是网络操作系统的升级往往不可控,因此业界开始重新审视UDP, HTTP/3 所使用的QUIC 就是基于UDP协议的。

HTTP/3 何时才能实施呢?整个互联网支持HTTP/3 可能还需要一段不短的时间吧!

参考资料:
  • 《HTTP 权威指南》

  • HTTPs://HTTP2.akamai.com/demo

  • HTTP://HTTP2.loadimpact.com/entry/

  • RFC 7540 - Hypertext Transfer Protocol Version 2 (HTTP/2) 

  • RFC 7541 - HPACK: Header Compression for HTTP/2

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

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

相关文章

poi java 其他_让POI架起Java与Office之间的桥梁一

本文将阐述如何用POI来读取/写入完整的Excel文件。作者:中国IT实验室 来源:中国IT实验室 2007年8月31日本文将阐述如何用POI来读取/写入完整的Excel文件。约定:POI项目2.0版现在已经接近正式发行阶段,开发进度迅速,不断…

vue ui框架_「webAPP」记录几款比较好用的vue 移动端的ui框架

有时在做项目时,不同场景的项目既要有网站,又要有手机端,为了快速开发,如果功能简单,要求不高的话,我们一般会用H5进行移动端的适配。如果采用纯html进行书写手机端的样式,往往UI的体验感非常差…

java定义基础变量语句_编程语言第一:JAVA语言基础,变量

在前面的几篇文章中我们介绍了Java的运行环境,以及Eclipse IDE的安装与使用。从今天开始我们的文章开始介绍Java开发语言的基础知识。今天主要介绍Java变量。一、什么是变量变量是指代在内存中开辟的存储空间,用于存放运算过程中需要用到的数据。例&…

python keras_深度学习:基于Keras的Python实践

部分初识1初识深度学习/21.1Python的深度学习/21.2软件环境和基本要求/31.2.1Python和SciPy/31.2.2机器学习/31.2.3深度学习/41.3阅读本书的收获/41.4本书说明/41.5本书中的代码/52深度学习生态圈/62.1CNTK/62.1.1安装CNTK/72.1.2CNTK的简单例子/82.2TensorFlow/8部分初识1初识…

php 模拟并发请求_PHP模拟并发请求

原理&#xff1a;使用curl_init()创建多个请求实例&#xff0c;再使用curl_multi_init()批量执行创建的多个请求实例。文件1&#xff1a;curl.php<?php $threads500;//并发请求次数$urlhttp://blog.cn/index.php?;//请求的url//创建一个未定义的curl句柄数组$charray();//…

spring.profiles.active配置了没生效_微服务架构之「 配置中心 」

在微服务架构的系列文章中&#xff0c;前面已经通过文章《微服务架构之「服务网关 」》介绍过了在微服务中服务网关的原理和应用&#xff0c;今天这篇文章我们继续来聊一聊微服务中另外一个重要模块&#xff1a;「 配置中心 」。后面还会继续介绍 服务框架、服务监控、服务治理…

php+正则匹配qq,正则表达式对qq号进行验证的实例

这篇文章主要介绍了正则表达式对qq号码进行校验的相关知识&#xff0c;非常不错&#xff0c;具有参考借鉴价值&#xff0c;需要的的朋友参考下吧废话不多说了&#xff0c;直接给大家贴代码了&#xff0c;具体代码如下所示&#xff1a;package 正则表达式;/*对QQ号码进行校验要求…

公招网报照片审核处理工具_消防员招录报名照片处理工具使用说明

消防员招录报名照片处理工具使用说明请将下载的压缩包文件全部解压后&#xff0c;在照片处理工具文件夹中&#xff0c;用鼠标双击 “消防员招录报名照片处理工具.exe” 运行照片处理工具软件。本工具是消防员招录报名照片处理专用工具&#xff0c;只有经本工具处理符合要求的照…

php树形数据结构是什么,数据结构 之 树

概述树的章节一般分两大部分&#xff1a; 一部分将树&#xff0c;一部分将二叉树&#xff1b;虽然二叉树也是树&#xff0c;但是二叉树足够特殊&#xff0c;足够有用&#xff0c;所以重点来讲&#xff1b;或者说&#xff0c;如果不是二叉树&#xff0c;树的家族也不会如此的德高…

python3解释器执行'abcdd'.endswith('cd')的结果是___python3解释器执行for x

【判断题】RAM通常由地址译码器、存储矩阵和读/写电路三部分组成。【单选题】Until we reduce our dependence on oil, we will be ( ) the ups and downs of the oil markets.【单选题】python3解释器执行 fork,v in{1:a,2:b}:print(k,v)的结果是():【单选题】He argues that …

java script中定义的var变量怎么在body中使用,深入分析JavaScriptvar中的预解析与副作用...

var的副作用隐式全局变量和明确定义的全局变量间有些小的差异&#xff0c;就是通过delete操作符让变量未定义的能力。通过var创建的全局变量(任何函数之外的程序中创建)是不能被删除的。无var创建的隐式全局变量(无视是否在函数中创建)是能被删除的。这表明&#xff0c;在技术上…

螺旋桨设计软件_第四届智能工业软件及设计技术研讨会暨2019天洑软件用户大会成功举办...

第四届智能工业软件及设计技术研讨会暨2019天洑软件用户大会于2019年6月13日-14日在辽宁省大连市召开。天洑软件用户大会至2019年已成功举办了四届&#xff0c;在历届会议中有来自中国、德国、瑞典、捷克、意大利、美国、加拿大、日本等各行业专家学者共同探讨最新的计算机智能…

php 上一条下一条,thinkPhp里添加显示上一条和下一条

newsinfo.php里的代码if($front[id]!null){$id $front[id];echo "上一条:$front[title]";}else{echo "上一条&#xff1a;没有了";}echo " ";if($after[id]!null){echo "下一条:$after[title]";}else{echo "下一条&#xff…

群晖 百度网盘_海康威视联合百度网盘推出NAS私有存储 贡献带宽获积分兑网盘会员...

此前百度网盘因为限速问题遭到不少用户的吐槽&#xff0c;随后百度网盘推出单次付费加速由于价格过高再次被吐槽。网盘类的服务也确实需要大量的硬盘空间和服务器带宽支撑&#xff0c;所以对用户来说最好的办法还是自己搭建网盘。自己搭建的网盘也就是私有云存储&#xff0c;放…

深信服python面试题_(完整版)往年的深信服笔试题(齐全)

•一&#xff0c;六道选择题(可以多选)1char*p"helloworld";p存储在()指向//堆栈charp[]"helloworld";p存储在()指向全局变量//数据段static变量//数据段分别在哪个地方&#xff1f;1数据段2代码段3堆4堆栈(此题可以配合同文件夹下的char.cpp)(二、例子程序…

matlab 特征值不排序,matlap 代码求解释!从这里开始即可%对特征值进行排序并去掉...

%人脸识别代码clear all % //removes all variables from the workspace. This frees up system memory.close all % //Delete specified figureclc% number of images on your training set.%训练集数目M16;%Chosen std and mean.%It can be any number that it is clos…

python有序队列_【Python】:拓展Queue实现有序不重复队列

最近手头有个需求是这样的&#xff0c;定期检查数据库获取失败任务并且进行重启。最早想到的是添加一个生产者&&消费者队列&#xff0c;但是发现很多棘手的问题。1.重启任务是调用的一个shell脚本然后在脚本中又调用python程序&#xff0c;所以任务完成的状态回传略纠结…

matlab ode45求解齿轮动力学,ode45求解多自由度动力学方程实例.doc

ode45求解多自由度动力学方程实例Ode45函数调用形式如下&#xff1a;[T,Y]ode45(odefun,tspan,y0)相关参数介绍如下&#xff1a;参数名称参数说明odefun用于存放待求解的方程的m文件名&#xff0c;方程必须用y’f(t,y)的形式存放tspan指定自变量范围的向量&#xff0c;通常用[t…

onenetsim定位功能吗_微信小程序新增后台定位功能,你会卸载地图APP用微信导航吗...

[PConline]8月8日&#xff0c;根据微信官方发布的消息显示&#xff0c;小程序新增后台定位功能&#xff0c;并对自动化测试功能进行了升级。据介绍&#xff0c;为了满足线路导航、路线记录等服务场景下&#xff0c;小程序需要长时间持续定位来提供服务。当用户主动将小程序设置…

pdo 错误 php,多语句查询中的PHP PDO错误

我在我的一个实时网络应用程序中遇到了这个问题.看来如果你通过PHP PDO向MysqL发出一个多语句查询,并且第一个语句是一个insert语句,而第二个语句是一个update语句,那么PDO :: nextRowset()函数不会返回正确的数字结果集(请注意,自PHP 5.3起,PDO应该支持每个MySQL查询的多个语句…