Skip to content

在HTTP GET请求中使用stream

node.js实现http请求

js
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)

get请求和response

通过req.method可获取请求方法

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

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

response和stream

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

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

var server = http.createServer(function(req, res) {
  var method = req.method
  if (method === 'GET') {
    var fileName = path.resolve(__dirname, 'data.txt')
    var stream = fs.createReadStream(fileName)
    stream.pipe(res)
  }
})

server.listen(8000)

使用stream对性能的提升

### 实际应用

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

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

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

总结

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


在http post请求中使用stream

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

var server = http.createServer(function(req, res) {
  var method = req.method
  if (method === 'POST') {
    req.on('data', function(chunk) {
      // 接受到部分数据
      console.log('chunk', chunk.toString().length)
    })
    req.on('end', function() {
      console.log('end')
      res.end('ok')
    })
  }
})
server.listen(8000)

post请求发送数据量若很大, res.on('data', ...) 要分多次才能把数据接受完毕

小结一下,request和response一样,本身也是一个stream对象,可以用stream的特性,那肯定也能提高性能。两者的区别在于,request是source类型,是stream的源头,而response是dest类型,是stream的目的地。

再举个例子,如果要把request请求的数据直接response,那么最快的方式就是res.pipe(res)

使用stream对性能的提升

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

var server = http.createServer(function(req, res) {
  var method = req.method
  if (method === 'POST') {
    var dataStr = ''
    req.on('data', function(chunk) {
      var chunkStr = chunk.toString()
      dataStr += chunkStr
    })
    res.on('end', function() {
      var fileName = path.resolve(__dirname, 'data.txt')
      fs.writeFile(fileName, dataStr)
      res.end('ok')
    })
  }
})

server.listen(8000)

用stream改良后如下:

js
var server = http.createServer(function(req, res) {
  var method = req.method
  if (method === 'POST') {
    var dataStr = ''
    req.on('data', function(chunk) {
      var chunkStr = chunk.toString()
      dataStr += chunkStr
    })
    res.on('end', function() {
      var fileName = path.resolve(__dirname, 'data.txt')
      var writeStream = fs.createWriteStream(fileName)
      res.pipe(writeStream)
      req.on('end', function() {
        res.end('ok')
      })
    })
  }
})

实际应用

和get请求使用stream场景类似,post请求使用stream的场景,主要是用于将接受的数据直接进行IO操作,例如:

  • 将接收的数据直接存储为文件
  • 将接收的数据直接post给其他的web server

总结

介绍了stream在http请求中的应用和性能提升,IO操作不仅仅包括网络IO,还包括文件IO,下一节讲解stream在文件操作中的使用,以及性能提升。

共 20 个模块,1301 篇 Markdown 文档。