内容简介:HTTP/2 协议的优点解析
作者丨wanago
译者丨小大非
HTTP 协议于 1991 年引入,至今已有近 30 年的历史。自第一个文档化版本 (后来称为 0.9) 以来,它已经经历了一段相当长的历程。在本文中,我们将简要回顾 HTTP 协议的发展历史,重点介绍 HTTP/2 带来了什么,以及我们如何从中获益。我们将使用 Node.js 服务端来实现它。
HTTP 的第一个版本只能传输超文本标记语言 (HTML) 文件,因此我们称之为超文本传输协议。它真的很简单,唯一可用的方法就是 GET。它没有 HTTP 头文件或状态代码。如果出现问题,服务器可以使用带有错误描述的 HTML 文件进行响应。
1996 年 1.0 版本出现了。与前一个版本相比,它进行了许多改进,其中最重要的是状态代码、POST 和 header 等附加方法。现在,我们可以使用 Content-Type 头来传输普通 HTML 之外的文件。
1997 年发布的 HTTP/1.1 引入了一些其它的改进。除了添加像 OPTIONS 这样的方法外,它还引入了 Keep-Alive 头。它允许一个连接对多个 HTTP 请求保持打开状态。因为这点,连接不必在每次请求之后关闭,然后再重新打开。在 HTTP/1.1 中,我们通常一次只能有 6 个连接。例如,如果其中一个请求由于服务器上的某些复杂逻辑而卡住,那么它们中的每一个都可以一次处理一个请求,整个连接就会冻结并等待响应。这个问题称为前端阻塞。
堆栈中有很多实现 HTTP/2 的方法。一种常见的方法可能是在 web 服务器上实现它,但是在本文中,我们在应用程序层中实现它,以便拓展 Node.js 的相关知识。因为浏览器不支持未加密的 HTTP/2,这意味着我们需要通过 HTTPS 协议实现 TLS 连接。要在本地完成此操作,我们使用以下命令生成证书:
openssl req -x509 -newkey rsa:4096 -keyout key.pem -out certificate.pem -days 365 -nodes
如果你想了解详细信息,请查看《使用 OpenSSL 证书实现 HTTPS》: https://wanago.io/2019/04/01/node-js-typescript-8-implementing-https-with-our-own-openssl-certificate/
import * as http2 from 'http2';
import * as fs from 'fs';
import * as util from 'util';
const readFile = util.promisify(fs.readFile);
async function startServer() {
const [key, cert] = await Promise.all([
readFile('key.pem'),
readFile('certificate.pem')
]);
const server = http2.createSecureServer({ key, cert })
.listen(8080, () => {
console.log('Server started');
});
server.on('stream', (stream, headers) => {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end('
Hello World
');});
server.on('error', (err) => console.error(err));
}
startServer();
即使使用 HTTP/1.1 进行 6 个并行连接也可能不够用,尤其是当我们遇到前端阻塞时。HTTP/2 通过允许一个连接同时处理多个请求解决了这个问题,这是因为即使其中一个请求被卡住,其它的请求也可以继续。在上面的这个简单示例中,我们使用普通 HTML 进行响应。每当有人向我们的服务器发出请求时,流事件就会触发。
如果你想了解更多关于流的信息,请查看《可读流的暂停和流动模式》和《可写流、管道和流程流》 《可读流的暂停和流动模式》链接: https://wanago.io/2019/03/04/node-js-typescript-4-paused-and-flowing-modes-of-a-readable-stream/ 《可写流、管道和流程流》链接: https://wanago.io/2019/03/11/node-js-typescript-5-writable-streams-pipes-and-the-process-streams/
在 headers 参数中,我们有即将到来的请求的所有 header。它是一种检查方法,比如请求的方法和路径。现在,由于我们使用 HTTP/2,浏览器使用一个非阻塞的连接。一个可以关注的例子是 Golang 团队创建的一个网格演示。在使用 HTTP/2 时,由于在同一连接上处理并行请求和处理前端阻塞问题,你可以看到性能的显著提高。
Golang 团队创建的一个网格演示链接: https://http2.golang.org/gophertiles
HTTP/2 使用了一种新的报头压缩算法,我们称之为 HPACK。一些参与定义 HTTP/2 协议的开发人员也在开发 SPDY,它以前也用于压缩报头。不幸的是,后来人们发现它容易受到 CRIME 攻击。HPACK 不仅使整个过程更加安全,而且在某些情况下速度更快。
当我们实现 HTTP/2 时,上面所有的改进都是开箱即用的。这并不是它全部的能力。通过服务器推送,我们现在可以在客户机缓存中填充数据。我们甚至可以在浏览器请求之前完成。一个基本的使用场景是当用户请求 index.html 文件时的情况。
server.on('stream', (stream, headers) => {
const path = headers[":path"];
switch(path) {
case '/': {
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end(`
"stylesheet" type="text/css" href="style.css">
Hello World
`);
break;
}
case '/style.css': {
stream.respond({
'content-type': 'text/css',
':status': 200
});
stream.end(`
body {
color: red;
}
`);
break;
}
default: {
stream.respond({
':status': 404
});
stream.end();
}
}
});
在上面的示例中,当用户访问主页时,它请求 index.html 文件。当它得到一个样式表时,它会注意到还需要 style.css 文件。在请求 index.html 和 style.css 之间有一些延迟,我们可以使用服务端推送来处理它。因为我们知道用户将需要 style.css 文件,所以可以将它与 index.html 一起发送。
server.on('stream', (stream, headers) => {
const path = headers[":path"];
switch(path) {
case '/': {
stream.pushStream({ ':path': '/style.css' }, (err, pushStream) => {
if (err) throw err;
pushStream.respond({
'content-type': 'text/css',
':status': 200
});
pushStream.end(`
body {
color: red;
}
`);
});
stream.respond({
'content-type': 'text/html',
':status': 200
});
stream.end(`
Hello World
`);
break;
}
case '/style.css': {
stream.respond({
'content-type': 'text/css',
':status': 200
});
stream.end(`
body {
color: red;
}
`);
break;
}
default: {
stream.respond({
':status': 404
});
stream.end();
}
}
});
现在使用 stream.pushStream 只要有人请求 index.html,我们就发送 style.css 文件。当浏览器处理它时,它会看到标记,并注意到它还需要 style.css 文件。由于服务端推送,它已经缓存在浏览器中,因此不需要发送另一个请求。
HTTP/2 旨在通过满足日益复杂的 web 页面的需求来提高性能。我们使用 HTTP 协议发送的数据量增加了,HTTP/2 通过处理前端阻塞等方法解决了这个问题。另外由于在同一连接上处理并行请求,这也解除了 HTTP/1.1 的一些限制。
原文链接:
https://wanago.io/2019/07/15/node-js-typescript-benefits-http2-protocol/
点个在看少个 bug ????
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
数学与生活(修订版)
[日] 远山启 / 吕砚山、李诵雪、马杰、莫德举 / 人民邮电出版社 / 2014-10 / 42.00元
数学是高等智慧生物的共有思维,是对真理的探索,对矛盾的怀疑,但它绝非一门晦涩难懂的学问,非应试目的的数学是纯粹而朴实的智慧。《数学与生活》为日本数学教育改革之作,旨在还原被考试扭曲的数学,为读者呈现数学的真正容颜,消除应试教学模式带来的数学恐惧感。 本书既包含了初等数学的基础内容,又包含了微分、积分、微分方程、费马定理、欧拉公式等高等数学的内容。作者运用了多个学科的知识。结合日常生活和东西方......一起来看看 《数学与生活(修订版)》 这本书的介绍吧!