大家好,我是小鑫同学。一位长期从事前端开发的编程爱好者,我信奉编程最重要的是分享。请跟随小鑫同学的步伐,一起带你畅游不一样的前端世界~
HTTP 协议经历了 20 多年的演进在 2018 年来到了 HTTP3.0 的时代,到现在时间 HTTP2.0 已经在大多数的主流站点得到了广泛的使用,可是你的网站升级到 2.0 版本了吗?今天就通过示例来演示如何从 1.1 版本升级到 2.0 版本,体验一下 2.0 版本的多路复用究竟能不能优化现有的站点呢?
1. 使用 NodeJs 实现 HTTP2.0
在下面的网页中包含了 24 张图片,在 HTTP1.1 版本的时候受浏览器限制,同一域名同时发起的请求数量将限制在 6~8 次。在 HTTP2.0 采用多路复用替换的原来的机制,相同域名也只占用同一个 TCP 链接完成数据交换。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>HTTP、HTTP2</title>
</head>
<body>
<img width="30%" height="20%" src="images/1e2b54c596f813e44138769b2e76f169.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/5dce78ea79845fcf2f1b62dbf3acf620.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/7ad706b7e6e0442cea9d4e0347cd487d.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/9d90986693450e14afe74db3a05e336a.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/46f3da0e924a0b798bfe461759b8779c.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/47d28a384c0aefea2d4152a7805a132a.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/75c804f11e2f9b3d3ad9adf6f143ac22.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/94bddbdc4d93fcf58b9e46b3feabee8e.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/500e4caf9a5b392fac176bc8dae8fb40.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/86627adf5e44df12be9e7ee436b6a28d.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/ae8e846f6fd915c67e26ab59fb1bf655.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/c22e0ae61c5759134c46ef1a63fc746e.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/c45b5212ef77b3f9b16660faef173517.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/c540e2e5a1aa4209c92ab9a4a7e3018d.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/c5734d100410e544e91edbcb7608d8bc.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/cde25fb6bd5df4ff66930faece0779f5.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/cfc76fef4149c84ee6bb82a251171f60.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/d383e4bd00949edf2b301ffb7585e8aa.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/e240d3b230d4fe71f9ef64e0bf855c3b.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/e528b014d2c0a4b69b5e58c61bfe47e7.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/f917bfe3a042f91b4213d53b383ca1fa.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/08e5d3f7c7d9e46bf0072f3296147f55.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/887a346047f75aca61108f06f07de9cc.jpeg" alt="" srcset="" />
<img width="30%" height="20%" src="images/3e12a1db86d48b881acbc2b7d24d995e.jpeg" alt="" srcset="" />
</body>
</html>
复制代码
1.1 编写 HTTP1.1 版本案例:
在 NodeJs 中 http 包默认使用的就是 HTTP1.1 版本协议,通过createServer
函数实现默认和图片访问的两种响应方式:
import http from "node:http";
import fs from "node:fs";
import cp from "node:child_process";
const server = http.createServer((req, res) => {
const url = req.url;
if (url === "/") {
const html = fs.readFileSync("index.html");
res.writeHead(200, {
"content-type": "text/html; charset=utf-8",
});
res.write(html);
res.end();
} else if (url?.startsWith("/images/")) {
const img = fs.readFileSync(`.${url}`);
res.writeHead(200, {
"content-type": "image/*",
});
res.write(img);
res.end();
}
});
server.listen(8553, () => {
console.log("> HTTP服务启动成功");
cp.exec("start http://localhost:8553");
});
复制代码
注:使用child_process
模块在服务启动后自动打开默认浏览器并跳转到[http://localhost:8553](http://localhost:8553)
;
1.2 编写 HTTP2.0 版本案例:
在使用 HTTP2.0 版本时需要同时支持 HTTPS 安全协议,我们就需要生成一份自签名证书,生成自签名证书可以使用mkcert开源项目:
# install mkcert from scoop
scoop bucket add extras
scoop install mkcert
复制代码
注:安装时请注意要科学一点;
HTTP2.0 版本协议在 NodeJs 中的 http2 模块中得到支持,使用时请注意 NodeJs 版本,我们在体验一些功能时做好切换 NodeJs 到较高的版本;
使用 NodeJs 中的 http2 模块实现案例,支持默认和图片访问的两种响应方式:
import http2 from "node:http2";
import fs from "node:fs";
import cp from "node:child_process";
// 配置自签名证书
const server = http2.createSecureServer({
key: fs.readFileSync("./keys/localhost-key.pem"),
cert: fs.readFileSync("./keys/localhost.pem"),
});
server.on("error", (err) => console.log(err));
server.on("stream", (stream, headers) => {
const path = headers[":path"];
if (path === "/") {
const html = fs.readFileSync("index.html");
stream.respond({
"content-type": "text/html; charset=utf-8",
":status": 200,
});
stream.write(html);
stream.end();
} else if (path?.startsWith("/images/")) {
const img = fs.readFileSync(`.${path}`);
stream.respond({
"content-type": "image/*",
":status": 200,
});
stream.write(img);
stream.end();
}
});
server.listen(8443, () => {
console.log("> HTTP2服务启动成功");
cp.exec("start https://localhost:8443");
});
复制代码
1.3 添加脚本并启动案例:
1.3.1 添加两个版本的启动脚本:
{
"scripts": {
"http": "npx esno ./server-http.ts",
"http2": "npx esno ./server-http2.ts"
}
}
复制代码
1.3.2 开启版本协议查看:
使用 Chrome 浏览器通过 NetWork 来观察网络请求情况时默认不支持协议版本的查看,或者查看不方便,这里可以启用一下:
1.3.3 调整浏览器网络请求速度:
在浏览器中调整网速来模拟慢网络下数据加载,方便观察请求的访问情况;
1.3.4 查看 HTTP1.1 下网络请求数限制:
在 1.1 版本中很明显看到网络在分批加载并且后续的网络需要等待前面网络请求完成后开始;
1.3.5 查看 HTTP2.0 下网络请求同时进行:
在 2.0 版本中看到几乎所有的请求都在同一时间发起,充分利用网络带宽的优势来同服务器进行数据的交换;
2. 为 Nginx 开启 HTTP2.0:
Nginx 版本和 OpenSSL 版本都有一定的要求,在实战使用时请注意版本问题,目前我在 Win 本上使用的 Nginx 版本是1.22.1
,OpenSSL 版本是1.1.1k 25 Mar 2021
;
nginx
├─ conf
│ ├─ ...
│ └─ nginx.conf
├─ html
│ ├─ images
│ │ ├─ ...
│ │ └─ f917bfe3a042f91b4213d53b383ca1fa.jpeg
│ └─ index.html
└─ nginx.exe
复制代码
2.1 配置默认 HTTP1.1 版本:
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /images/* {
root html;
}
}
复制代码
2.2 配置 HTTP2.0 版本和自签名证书:
server {
listen 443 ssl http2;
server_name localhost;
ssl_certificate ../../keys/localhost.pem;
ssl_certificate_key ../../keys/localhost-key.pem;
location / {
root html;
index index.html index.htm;
}
location /images/* {
root html;
}
}
复制代码
在启动 Nginx 服务后,重新观察[http://localhost/](http://localhost/)
、[https://localhost/](https://localhost/)
在 NetWork 请求情况可以得到了 NodeJs 版本相同的结果;
3. 已升级 HTTP2.0 版本网站:
3.1 百度图片搜索:
3.2 微博主页:
3.3. 今天头条主页:
3.4 稀土掘金主页:
3.5 InfoQ 主页:
总结
通过案例对比似乎发现 HTTP2.0 版本的协议似乎并没有启到什么效果,但是网络的优化也需要方方面面的考虑,在主流网站几乎全部支持了 HTTP2.0 时候我觉得有必要考虑将自己还没有升级 2.0 的网站提上日程。更好的体验 HTTP2 优势的案例参照:https://http2.akamai.com/demo;
本文项目已推送至 GitHub,欢迎克隆演示:git clone git@github.com:OSpoon/awesome-examples.git
如果看完觉得有收获,欢迎点赞、评论、分享支持一下。你的支持和肯定,是我坚持写作的动力~最后可以关注我 @小鑫同学。欢迎点此扫码加我微信fe-xiaoxin交流,共同进步(还可以帮你 fix🐛)~
评论