node http keep-alive demo

发布时间:2020-06-24 02:24:19发布者:admin浏览数:

http keep-alive 相关资料非常多,如果深挖,那可能就长篇大论了,不合适普及,这只是一篇新手入门引导,

主要讲解 node 下 http 请求的坑,以及 keep-alive 的简单使用,后续才会详细剖析原理。


起因

我司使用 node 做中间层开发,所以 api 都是 node 代理转发的,虽然目前 qps 不是特别高,都能满足需求,但压测总归是有的。

不压不知道,一压,emmmmm。。。


搭建个纯净的 node 请求测试环境

先不说业务,我们来搭建个最简单的测试环境,看看压测工具能跑到多少 QPS。

然后我们写个 api 代理模块看看能跑到多少。


使用 node 官方例子 https://nodejs.org/en/about/。

[JavaScript] 纯文本查看 复制代码

const http = require('http');const hostname = '127.0.0.1';const port = 3000;const server = http.createServer((req, res) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World\n');});server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`);});

然后我们用 wrk 来压测,因为简单方便。


参数 -c 并发数,就想象成同时请求后台 api 的数量,一个页面往往会调用3-5个后台接口。

参数 -d 持续时间,这就是压测本质啊,持续越久,效果越真实,因为很多时候后面会挂掉的。


看看 10 并发,持续 10 秒的情况。

[Shell] 纯文本查看 复制代码

$ wrk -c 10 -d 10 http://localhost:3000Running 10s test @ http://localhost:3000 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 523.02us 129.44us 4.04ms 92.33% Req/Sec 9.59k 550.11 10.55k 82.67% 192745 requests in 10.10s, 25.37MB readRequests/sec: 19083.81Transfer/sec: 2.51MB

可以看出 Req/Sec 的 Avg 值,就是平均 QPS 为 9.59k,因为默认开了2线程,所以总 QPS 为 19k。


好了,测试环境和测试结果已经有了直观的展现。

下面搭建 node 接口代理然后重新压测。


node 接口代理

我们由于业务需求,没用 http-proxy 做直接的代理转发,而是基于 got 模块,自定义的接口模型。


我们先不考虑业务开销,直接代理转发看看结果。

[JavaScript] 纯文本查看 复制代码

const http = require('http');const got = require('got');const hostname = '127.0.0.1';const port = 8000;const server = http.createServer((req, res) => { got.get('http://localhost:3000/').then(({ body }) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end(body); }).catch((err) => console.log(err));});server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`);});

代码跟刚才一样,只是多了一层 got 代理接口。

这里没用 got stream 直接 pipe 给 res,因为我们的代理接口中会做其他业务操作。


现在来压测下这个服务的情况吧。

[Shell] 纯文本查看 复制代码

$ wrk -c 10 -d 10 http://localhost:8000Running 10s test @ http://localhost:8000 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 13.63ms 20.29ms 193.78ms 94.45% Req/Sec 522.58 126.90 660.00 89.23% 10237 requests in 10.03s, 1.35MB readRequests/sec: 1020.52Transfer/sec: 137.53KB

有点慌,什么情况,怎么会相差这么多。


我们在 3000 服务中加入 console.log(req.headers); 看看 headers 字段。

[JavaScript] 纯文本查看 复制代码

const server = http.createServer((req, res) => { console.log(req.headers); // 输出 headers res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end('Hello World\n');});

然后访问 8000 服务,看到控制台输出:

[JavaScript] 纯文本查看 复制代码

{ 'user-agent': 'got/9.3.2 (https://github.com/sindresorhus/got)', 'accept-encoding': 'gzip, deflate', host: 'localhost:3000', connection: 'close' }

其中 connection 所以每次请求都会重新建立 tcp 连接,浪费了不少性能。


接下来我们要打开 keep-alive 提升代理性能。


开启 keep-alive

安装 agentkeepalive 模块,这是 fengmk2 大佬封装的模块,我们直接使用看看效果先。

[Shell] 纯文本查看 复制代码

$ yarn add agentkeepalive

然后在 8000 服务中开启代理。

[JavaScript] 纯文本查看 复制代码

const http = require('http');const got = require('got');const Agent = require('agentkeepalive');const agent = new Agent();const hostname = '127.0.0.1';const port = 8000;const server = http.createServer((req, res) => { got.get('http://localhost:3000/', { agent }).then(({ body }) => { res.statusCode = 200; res.setHeader('Content-Type', 'text/plain'); res.end(body); }).catch((err) => console.log(err));});server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`);});

重新启动,访问 8000 服务,查看 3000 服务控制台。

[JavaScript] 纯文本查看 复制代码

{ 'user-agent': 'got/9.3.2 (https://github.com/sindresorhus/got)', 'accept-encoding': 'gzip, deflate', host: 'localhost:3000', connection: 'keep-alive' }

看到已经开启了 keep-alive,我们把 3000 服务中的 log 先关掉,否则影响结果。

[Shell] 纯文本查看 复制代码

$ wrk -c 10 -d 10 http://localhost:8000Running 10s test @ http://localhost:8000 2 threads and 10 connections Thread Stats Avg Stdev Max +/- Stdev Latency 5.32ms 1.84ms 19.30ms 89.87% Req/Sec 0.96k 69.30 1.06k 78.50% 19141 requests in 10.02s, 2.52MB readRequests/sec: 1910.43Transfer/sec: 257.46KB

可以看到性能提升了 1 倍,将近 1k 了,但跟原服务 9.59k 还是相差太多。


目前我们只能开多进程来提升整体 QPS 了。

比如开 9 进程,每个进程都能吃到近 1k,差不多可以吃满源服务。

但如果你开了 10 进程甚至更多,那瓶颈就会在源服务上,就需要给源服务加 cpu 或加服务器。


小结

这里还有个会影响结果的因素,而且影响会比较大。

因为是我本地测试,两个服务都跑本地,要严谨的话,应该跑在服务器上,或相同配置的虚拟机中。

不过本文意图是体验 keep-alive 和怎么用 node 吃满接口服务。

所以就不做那么严谨的测试了。


还要吐槽一点,node http 请求,性能真是低下啊,或者是我不知道怎么正确的使用。

因为 autocannon 压测工具,也是 node 写的,但他能吃满,我们直接写请求,只能达到 1/10。


我自己写了个基于 net 的 http 1.1 请求 demo 测试,只提升了100左右,并没有特别大的改进。

因为水平有限,没写基于 net + keep-alive 的 http 1.1 测试,所以不能下结论。


后续我会慢慢研究 keep-alive 然后记录分享的。

  网站建设分类
程序开发 |  系统教程 |  软件应用 |  图形图像 |  网络应用 |  站长教程 |  网站建设 |  视频教程 |  硬件维护 |  IT资讯 |  中国it动力网
本站发布的系统与软件仅为个人学习测试使用,请在下载后24小时内删除,不得用于任何商业用途,否则后果自负,请支持购买微软正版软件!
如侵犯到您的权益,请及时通知我们,我们会及时处理。
Copyright @ 2019 中国it动力网 网站导航