当前位置: 首页 > 后端技术 > Node.js

使用Node.jsStreamAPI降低服务器端内存消耗的一个具体例子

时间:2023-04-04 01:23:03 Node.js

让我们看一个例子来展示使用流编程思想在内存消耗方面的巨大优势。让我们先创建一个大文件:constfs=require('fs');constfile=fs.createWriteStream('./big.file');对于(让i=0;i<=1e6;i++){文件。write('这是一个大文件。\n');}file.end();fs模块可用于使用流接口读取和写入文件。在上面的示例中,我们通过向可写流写入100万行的循环将数据写入big.file。运行上面的代码会生成一个大约400MB的文件。这是一个简单的NodeWeb服务器,专为大文件服务而设计:constfs=require('fs');constserver=require('http').createServer();server.on('request',(req,res)=>{fs.readFile('./big.file',(err,data)=>{if(err)throwerr;res.end(data);});});server.listen(8000);启动服务器,它消耗大约8MB的初始内存。使用浏览器访问服务器后,内存消耗跃升至434.8MB。我们基本上将整个big.file内容放在内存中,然后再将其写入响应对象。这是非常低效的。HTTP响应对象(上面代码中的res)也是一个可写流。这意味着如果我们有一个表示big.file内容的可读流,我们可以将两者相互连接并获得几乎相同的结果,而无需消耗约400MB的内存。Node的fs模块可以使用createReadStream方法为我们提供任何文件的可读流。我们可以将它通过管道传递给响应对象:constfs=require('fs');constserver=require('http').createServer();server.on('request',(req,res)=>{constsrc=fs.createReadStream('./big.file');src.pipe(res);});server.listen(8000);我们现在访问上面重新实现的服务器,发现内存消耗大大减少了。这是因为,当客户端请求那个大文件时,我们一次将它传输一个块,这意味着我们根本不会在内存中缓冲它的整个大文件内容。内存使用量增加了大约25MB,仅此而已。我们可以使测试场景更极端一些:用500万行而不是100万行重新生成big.file会使文件大于2GB,这实际上大于Node.js中的默认缓冲区限制。如果您尝试使用fs.readFile提供文件,默认情况下您将收到内存不足错误。但是使用fs.createReadStream,将2GB的数据流式传输给请求者是完全没有问题的,最重要的是,进程内存使用率差不多。