为了账号安全,请及时绑定邮箱和手机立即绑定

目录

手机
阅读

扫一扫 手机阅读

两小时学会 Node.js stream

原价 ¥ 9.99

立即订阅 ¥ 9.99
02 在 http get 请求中使用 stream
更新时间:2019-06-12 14:46:18
只有在那崎岖的小路上不畏艰险奋勇攀登的人,才有希望达到光辉的顶点。

——马克思

上一节提到,stream 的应用场景都是 IO 操作,包括网络 IO 和文件 IO 。本节主要介绍 http 请求中的 get 请求如何应用 stream ,以及应用 stream 之后对性能的提升。

目录

本节的主要内容:

  • node.js 实现 http 请求
  • get 请求和 response
  • response 和 stream
  • 使用 stream 对性能的提升
  • 应用场景

node.js 实现 http 请求

先贴出一段上一节中介绍过的一段代码,如下所示。这段代码就创建了一个服务,监听 8000 端口。有请求进来,就去读取 data.txt 这个文件,然后返回给客户端。

var http = require('http');
var fs = require('fs');
var path = require('path');

var server = http.createServer(function (req, res) {
    var fileName = path.resolve(__dirname, 'data.txt');
    fs.readFile(fileName, function (err, data) {
        res.end(data);
    });
});
server.listen(8000);

下面将这段代码真正运行起来。找一个目录,然后新建 test1.js 文件,然后把这段代码写入其中。然后再新建 data.txt 文件,随便写点什么文本内容,例如123456。然后打开命令行,定位到这个文件夹,运行 node test1.js ,打开浏览器访问 http://localhost:8000/ 即可看到效果。

get 请求和 response

本节只关注 get 请求,通过 req.method 可获取请求方法,因此将代码做如下改造。

var http = require('http');
var fs = require('fs');
var path = require('path');

var server = http.createServer(function (req, res) {
    var method = req.method; // 获取请求方法
    if (method === 'GET') { // 暂只关注 get 请求
        var fileName = path.resolve(__dirname, 'data.txt');
        fs.readFile(fileName, function (err, data) {
            res.end(data);
        });
    }
    // 其他 method 暂时忽略
});
server.listen(8000);

将代码修改在 test1.js 中,重新运行 node 并刷新浏览器,依然可以看到效果。

http 常见的有 get 和 post 请求,get 请求本意是获取数据,即 response ,post 请求本意的上传数据,即 request 。本节只关注 get 请求,也就代表本节只关注 http 请求的 response 。

response 和 stream

response 常用的 API 有 send end 等,如上面代码中的 res.end(data) ,但是 response 也是一个 stream 对象。大家再次回顾一开始的管道换水的图,以及 source.pipe(dest) 模型,response 就是一个 dest 。

图片描述

因此,之前的代码可以做出如下改动。

var http = require('http');
var fs = require('fs');
var path = require('path');

var server = http.createServer(function (req, res) {
    var method = req.method; // 获取请求方法
    if (method === 'GET') { // 暂只关注 get 请求
        var fileName = path.resolve(__dirname, 'data.txt');
        var stream = fs.createReadStream(fileName);
        stream.pipe(res); // 将 res 作为 stream 的 dest
    }
    // 其他 method 暂时忽略
});
server.listen(8000);

从之前的章节学习中我们知道 fs.createReadStream() 可以创建一个读取文件的 stream 对象,通过 pipe 可以将数据传递下去,这里就传递给了 response 。修改 test1.js 并创新运行 node ,刷新浏览器即可看到效果。

使用 stream 对性能的提升

现在大家都知道使用 stream 比直接一次性操作 IO 性能更好,但是具体好多少,不放做一个压力测试。首先,把现有的 data.txt 搞大一点,拷贝一些文字进去,然后多复制粘贴几次,让它大概有 5M 大小。然后用 ab 工具对两种方式做一个压力测试。

ab 全称 Apache bench ,是 Apache 自带的一个工具,因此使用 ab 必须要安装 Apache 。mac os 系统自带 Apache ,windows 用户视自己的情况进行安装。运行 ab 之前先启动 Apache ,mac os 启动方式是 sudo apachectl start

安装启动 Apache 完成之后,运行 ab -n 100 -c 100 http://localhost:8000/ 命令,即可进行测试。其中 -n 100 表示先后发送 100 次请求,-c 100 表示一次性发送的请求数目是 100 个。

下面,分别对未使用 stream 和使用了 stream 的两种情况进行测试,结果如下:

图片描述

上图可以看出用了 stream 之后,各个重要指标都有所提升。拿最重要的吞吐率(Requests per second)来说,从 118.23 变为 188.40 ,这可谓是一个非常大的性能提升 —— 别忘了,我们的成本仅仅是改了两行代码而已。而且,操作的文件体积越大,越能体现 stream 的价值。

实际应用

从上面例子可以看出,对 response 使用 stream 特性能提高性能。因此,在 nodejs 中如果要返回的数据是经过 IO 操作得来的,例如上面例子中读取文件内容,可以直接使用 stream.pipe(res); 这种方式,而不要再用 res.end(data); 了。

这种应用的实例应该比较多,主要有两种场景:

  • 使用 node.js 作为服务代理,即客户端通过 node.js 服务作为跳板去请求其他服务,返回请求的内容
  • 使用 node.js 做静态文件服务器,直接返回静态文件

总结

本节主要讲解了 node.js 如何处理 http 的 get 请求,以及如何对 response 使用 stream 特性,并做了压力测试证明使用 stream 可以提高性能。学完本节希望你能掌握:

  • node.js 如何搭建 http 请求
  • response 也是一个 stream 对象,可以作为参数被传入 pipe 方法
  • ab 工具的使用,以及测试结果的简单分析

本节讲完了 get 请求的相关内容,下一节将重点关注 http 的 post 请求。

}
立即订阅 ¥ 9.99

你正在阅读课程试读内容,订阅后解锁课程全部内容

两小时学会 Node.js stream
立即订阅 ¥ 9.99

举报

0/150
提交
取消
意见反馈 邀请有奖 帮助中心 APP下载
官方微信