Node.js&Express.js HTTP应用超时设置
Node.js创建的HTTP服务器,其对于每个客户端请求的默认连接时长是2分钟(120秒)。如果在这个时间内,服务器没有发送响应信息(response
),客户端的连接就会被重置。时间过长的请求响应会造成极差的用户体验,而且会造成IO的阻塞,对于单线程运行的Node.js应用来说,这种影响简直是灾难性的。合理的设置应用的超时时间非常重要。
1. Node.jshttp
模块对超时的处理
在Node.js中,创建一个HTTP服务器使用http
模块。
1.1 创建一个HTTP服务器
使用Node.js的http
模块,可以很简单实现一个HTTP服务器:
const http = require('http'); const hostname = '127.0.0.1'; const port = 1337; var server = http.createServer((req, res) => { res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('Hello World\n'); }) server.listen(port, hostname, () => { console.log(`Server running at http://${hostname}:${port}/`); });
在上面的示例中,我们使用http.createServer
创建了一个HTTP服务器server
,它是一个http.Server
实例。
在这个服务器中,我们添加了一个HTTP客户端请求监听函数,该函数包括两个参数:req
和res
。其中,req
是一个客户端请求对象包含了客户端的请求信息,它是一个http.IncomingMessage
实例。而res
是服务器响应对象,它是一个http.ServerResponse
实例,服务器处理完用户请求后通过访对象向客户端返回响应信息
1.2 http
模块的超时设置
服务端的超时设置
对于一个HTTP服务器来说,我们可能会设置以下两种类型的超时:
用户请求的超时
:即上例中http.IncomingMessage
实例-req
用户请求时间过长,会导致服务器停留在一个用户请求的接收状态,从而阻碍其它用户请求的进入。
服务器响应的超时
:即上例中http.ServerResponse
实例-res
服务器响应时间过长,会导致用户长时间接收不到服务器响应信息,影响用户体验和其它用户请求的处理
Node.js HTTP服务器设置超时使用setTimeout()
方法。http.Server
、http.IncomingMessage
和http.ServerResponse
中都有一个setTimeout()
方法。server.setTimeout()
会设置所有用户请求和服务器响应的超时时间,而req.setTimeout()
只能针对本次请求超时时间进行设置,res.setTimeout()
只能针对本次请求的服务器响应超时时间进行设置。我们可以像下面这样在HTTP服务端设置超时:
将所有的用户请求和服务器响应超时时间设置为5秒:
server.setTimeout(5000);
对于某一个比较耗时的用户请求(如:图片上传),我们将用户请求超时时间设置为20秒:
req.setTimeout(20*1000);
对于一个需要在服务器进行较长时间处理用户请求,我们将服务器响应的超时时间设置为10秒:
res.setTimeout(10*1000);
客户端的超时设置
Node.js的http
模块除了可以做为HTTP服务器使用,来处理和响应用户请求外。还可以做为HTTP客户端来使用,来发送客户端请求。
http
模块中的ClientRequest
对象实现了HTTP客户端功能,该对象同样提供了一个setTimeout()
方法,用于设置请求的超时时间,当服务器超时未响应时,客户端对象会重置到服务器的链接。
如,我们可以像下面这样创建一个HTTP客户端,并设置请求的超时时间:
const http = require('http'); const options = { host: 'itbilu.com', method: 'GET', port: 80, path: '/' } var req = http.request(options); req.setTimeout(2000); req.on('response', (res) => { res.setEncoding('utf8'); res.on('data', function(chunk){ console.log('收到数据:%s', chunk); }); res.on('end', function(){ console.log(res.trailers); }); }); req.end();
注意:所有的超时设置都是以毫秒
为单位,当设置为0
时表示永不超时。
2. Express.js
的超时设置
Express.js
框架是在http
模块的基础上构建的一个HTTP服务器模块,因此我们也可以像http
模块那样设置所有HTTP请求的用户请求和服务器响应超时时间,也可以针对某一个HTTP请求设置用户请求和服务器响应超时时间。
2.1 Express.js
所有的请求超时时间
类似Node.js原生的HTTP服务器设置,我们对Express.js
应用所有请求的用户请求和服务器响应超时时间进行设置:
var app = require('../app'); app.set('port', process.env.PORT || 3000); var server = app.listen(app.get('port'), function() { debug('Express服务器运行于:' + server.address().port); }); server.setTimeout(1000); server.on('timeout', function(){ console.log('超时了'); })
2.2 使用Express.js
中间件设置超时
Express.js
提供了强大的中间件机制,利用这一机制我们可以更为灵活的设置HTTP服务器超时时间。
如,我们可以在app.js
文件中添加如下处理程序,分别设置请求和服务器响应的超时时间,当然也可以只设置请求超时或服务器响应超时时间:
app.use(function(req, res, next) { // 设置所有HTTP请求的超时时间 req.setTimeout(5000); // 设置所有HTTP请求的服务器响应超时时间 res.setTimeout(5000); next(); });
对比较某一个比较耗时的用户请求,或需要较多响应时间才能完成处理的请求,我们可以其路由处理方法或路由中间件中单独设置超时时间:
router.post('/file', function(req, res) { req.setTimeout(20*1000) // 一些处理…… });
转自:https://itbilu.com/nodejs/core/4yHX3Aiie.html
参考:https://juejin.cn/post/6871176409278332935