【12-19】HTTP 2.0 和 HTTP1.1 区别

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了【12-19】HTTP 2.0 和 HTTP1.1 区别相关的知识,希望对你有一定的参考价值。

参考技术A

减少了网络的来回时间,可以同时并且几个TCP连接,如果太多的话,会加大服务器的压力(D-DOS攻击),各个浏览器会有自己想法,会考虑服务器的感受

采用头部压缩(字典)
二进制分帧层【解决了队头阻塞,因为Http1.0发送的数据是有顺序的,客户端可以处理交错的返回数据顺序】

多路复用允许单一的 HTTP/2 连接同时发起多重的请求-响应消息。看个例子:

整个访问流程第一次请求index.html页面,之后浏览器会去请求style.css和scripts.js的文件。左边的图是顺序加载两个个文件的,右边则是 并行加载 两个文件。

我们知道HTTP底层其实依赖的是TCP协议,那问题是在同一个连接里面同时发生两个请求响应着是怎么做到的?

首先你要知道,TCP连接相当于两根管道(一个用于服务器到客户端,一个用于客户端到服务器),管道里面数据传输是通过字节码(TCP是面向字节的)传输,传输是有序的,每个字节都是一个一个来传输。

例如客户端要向服务器发送Hello、World两个单词,只能是先发送Hello再发送World,没办法同时发送这两个单词。不然服务器收到的可能就是HWeolrllod(注意是穿插着发过去了,但是顺序还是不会乱)。这样服务器就懵b了。

接上面的问题,能否同时发送Hello和World两个单词能,当然也是可以的,可以将数据拆成包,给每个包打上标签。发的时候是这样的 ①H ②W ①e ②o ①l ②r ①l ②l ①o ②d 。这样到了服务器,服务器根据标签把两个单词区分开来。实际的发送效果如下图:

要实现上面的效果我们引入一个新的概念就是: 二进制分帧

二进制分帧层 在 应用层(HTTP/2)和传输层(TCP or UDP)之间。HTTP/2并没有去修改TCP协议而是尽可能的利用TCP的特性。

在二进制分帧层中, HTTP/2 会将所有传输的信息分割为帧(frame),并对它们采用二进制格式的编码 ,其中 首部信息会被封装到 HEADER frame,而相应的 Request Body 则封装到 DATA frame 里面。

HTTP 性能优化的关键并不在于高带宽,而是低延迟 。TCP 连接会随着时间进行自我「调谐」,起初会限制连接的最大速度,如果数据成功传输,会随着时间的推移提高传输的速度。这种调谐则被称为 TCP 慢启动。由于这种原因,让原本就具有突发性和短时性的 HTTP 连接变的十分低效。

HTTP/2 通过让所有数据流共用同一个连接,可以更有效地使用 TCP 连接,让高带宽也能真正的服务于 HTTP 的性能提升。

通过下面两张图,我们可以更加深入的认识多路复用:

HTTP/1

HTTP/2

总结下:多路复用技术:单连接多资源的方式,减少服务端的链接压力,内存占用更少,连接吞吐量更大;由于减少TCP 慢启动时间,提高传输的速度

为什么要压缩?在 HTTP/1 中,HTTP 请求和响应都是由「状态行、请求 / 响应头部、消息主体」三部分组成。一般而言,消息主体都会经过 gzip 压缩,或者本身传输的就是压缩过后的二进制文件(例如图片、音频),但状态行和头部却没有经过任何压缩,直接以纯文本传输。

随着 Web 功能越来越复杂,每个页面产生的请求数也越来越多,导致消耗在头部的流量越来越多,尤其是每次都要传输 UserAgent、Cookie 这类 不会频繁变动 的内容,完全是一种浪费。

我们再用通俗的语言解释下,压缩的原理。头部压缩需要在支持 HTTP/2 的浏览器和服务端之间。

维护一份相同的静态字典(Static Table),包含常见的头部名称,以及特别常见的头部名称与值的组合;

维护一份相同的动态字典(Dynamic Table),可以动态的添加内容;

支持基于静态哈夫曼码表的哈夫曼编码(Huffman Coding);

静态字典的作用有两个:

1)对于完全匹配的头部键值对,例如 “:method :GET”,可以直接使用一个字符表示;

2)对于头部名称可以匹配的键值对,例如 “cookie :xxxxxxx”,可以将名称使用一个字符表示。

HTTP/2 中的静态字典如下(以下只截取了部分,完整表格在这里):

同时,浏览器和服务端都可以向动态字典中添加键值对,之后这个键值对就可以使用一个字符表示了。需要注意的是,动态字典上下文有关,需要为每个 HTTP/2 连接维护不同的字典。在传输过程中使用,使用字符代替键值对大大减少传输的数据量。

服务端推送是一种在客户端请求之前发送数据的机制。当代网页使用了许多资源:HTML、样式表、脚本、图片等等。在HTTP/1.x中这些资源每一个都必须明确地请求。这可能是一个很慢的过程。浏览器从获取HTML开始,然后在它解析和评估页面的时候,增量地获取更多的资源。因为服务器必须等待浏览器做每一个请求,网络经常是空闲的和未充分使用的。

为了改善延迟,HTTP/2引入了server push,它允许服务端推送资源给浏览器,在浏览器明确地请求之前。一个服务器经常知道一个页面需要很多附加资源,在它响应浏览器第一个请求的时候,可以开始推送这些资源。这允许服务端去完全充分地利用一个可能空闲的网络,改善页面加载时间。

import http = require('http'); 的区别并从'http'导入*作为http;?

【中文标题】import http = require(\'http\'); 的区别并从\'http\'导入*作为http;?【英文标题】:Difference between import http = require('http'); and import * as http from 'http';?import http = require('http'); 的区别并从'http'导入*作为http;? 【发布时间】:2016-06-14 04:16:45 【问题描述】:

我找不到有价值的 NodeJS with Typescript 教程,所以我在无指导下潜入水中,果然我有一个问题。

我不明白这两行之间的区别:

import * as http from 'http';
// and
import http = require('http');

它们的功能似乎相同,但我想它们的行为可能存在一些细微差别,否则它们中的一个可能不存在。

我明白第一种方法可以让我有选择地从一个模块导入,但如果我要导入所有模块,那么两者之间有区别吗?有首选方法吗?如果我从自己的文件中导入,会发生什么变化吗?

【问题讨论】:

Typescript import/as vs import/require?的可能重复 New es6 syntax for importing commonjs / amd modules i.e. `import foo = require('foo')`的可能重复 【参考方案1】:

在第一种形式中,您在代码中创建一个 http 对象(完全干净),然后,解释器将在 http 模块中查找每个可能的导入并附加它,一个一个,到你代码中的 http 对象,这比你获得 module.exports 对象的第二种形式慢一点(不多)在 http 模块中定义,然后将此引用复制到代码中的新 http 对象,这是具有特定上下文的节点特殊函数中的对象,而不仅仅是一个对象使用模块的内容在您的代码中创建。

【讨论】:

【参考方案2】:
import http = require('http') //Common JS

这是常见的 JS 模块。在 12.2 版本之前,这是在 node JS 中使用模块的唯一方法。

import * as http from 'http'; //ES 6

这是 ES6 模块。在 ECMAScript 6 标准中,Javascript 原生支持模块。 Node JS 在 12.2 版本中实现了这个特性。

在这两个中,我总是更喜欢 ES6 模块,因为它是 javascript 实现的一部分。浏览器也支持 ES6 模块。但是浏览器不支持Common JS,因为它是同步的。 AMD 模块在 ES 6 之前的浏览器中使用,因为它不像 CommonJS 那样是异步的

【讨论】:

【参考方案3】:

在您将模块类型配置为 common JS 的节点环境中,输出将是相同的。其他模块框架将使用不同的语法,并且通过使用第一种方法,您可以灵活地随意更改它。

关于import * as http from 'http'; 方法的另一个注意事项是它是 ES6 模块导入语法,因此一旦您处于完全支持 ES6 的环境中,您的导入就可以正常工作。

【讨论】:

以上是关于【12-19】HTTP 2.0 和 HTTP1.1 区别的主要内容,如果未能解决你的问题,请参考以下文章

HTTP1.0 1.1 2.0 3.0梳理

HTTP1.0 HTTP 1.1 HTTP 2.0主要区别

长连接,短连接及WebSocket介绍(含http1.0,1.1,2.0相关)

GO HTTP1.1 与 HTTP2.0 的使用和简单分析

HTTP 1.0、1.1、2.0、3.0区别

一文搞懂HTTP2.0和HTTP1.0的区别