
超时控制主要涉及服务器端连接超时和客户端请求超时两大场景
一、服务器端超时设置(http.Server 相关)
服务器端的超时主要针对客户端连接:当客户端与服务器建立 TCP 连接后,如果长时间没有数据交互(如客户端未发送请求、或请求未完成),服务器可以主动断开连接,释放资源。
1. server.setTimeout(msecs[, callback])
- 作用:设置客户端连接的超时时间(从连接建立到数据交互的最大间隔)。
- 参数:
msecs:超时时间(毫秒),默认值为5000(5 秒)。callback(可选):超时事件的回调函数,等同于监听'timeout'事件。
- 行为:当连接超时后,会触发服务器的
'timeout'事件,同时底层 TCP 套接字(socket)会被标记为超时状态。 - 注意:超时后不会自动关闭连接,需手动调用
socket.destroy()关闭,否则连接会保持。
2. 'timeout' 事件(服务器端)
- 触发时机:客户端连接超时(超过
setTimeout设置的时间)时触发。 - 参数:
socket:超时的 TCP 套接字对象(net.Socket实例)。
- 用途:通常在事件回调中手动关闭超时连接,避免资源泄漏。
示例:服务器端设置连接超时
const http = require('http');
const server = http.createServer((req, res) => {
// 模拟耗时处理(若客户端 3 秒内未发送完整请求,会触发超时)
setTimeout(() => {
res.end('处理完成');
}, 4000);
});
// 设置超时时间为 3 秒(3000 毫秒)
server.setTimeout(3000, (socket) => {
console.log('连接超时(通过 callback 处理)');
// 手动关闭超时连接
socket.destroy();
});
// 或通过 'timeout' 事件处理
server.on('timeout', (socket) => {
console.log('连接超时(通过事件监听处理)');
socket.destroy(); // 关闭连接,避免资源占用
});
server.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
});
说明:
- 若客户端在 3 秒内未完成请求(如仅建立连接但未发送数据),服务器会触发
'timeout'事件,调用socket.destroy()强制关闭连接。 - 超时时间应根据业务场景设置(如 API 服务可设 5-10 秒,文件上传可设更长时间)。
二、客户端超时设置(http.ClientRequest 相关)
客户端的超时主要针对请求过程:当客户端发送请求后,若服务器长时间未响应(无数据返回),客户端可以主动终止请求,避免无限等待。
1. req.setTimeout(msecs[, callback])
- 作用:设置客户端请求的超时时间(从请求发送到收到响应的最大间隔)。
- 参数:
msecs:超时时间(毫秒),无默认值(需手动设置,否则可能无限等待)。callback(可选):超时事件的回调函数,等同于监听'timeout'事件。
- 行为:当请求超时后,会触发
'timeout'事件,但不会自动终止请求,需手动调用req.abort()或req.destroy()终止。
2. 'timeout' 事件(客户端)
- 触发时机:请求超时(超过
setTimeout设置的时间)时触发。 - 用途:在事件回调中终止请求,释放本地资源。
示例:客户端设置请求超时
const http = require('http');
const options = {
hostname: 'localhost',
port: 3000,
path: '/slow', // 假设该接口会延迟 5 秒响应
method: 'GET'
};
const req = http.request(options, (res) => {
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
console.log('响应内容:', data);
});
});
// 设置请求超时时间为 3 秒(若 3 秒内无响应,则触发超时)
req.setTimeout(3000, () => {
console.log('请求超时,终止请求');
req.abort(); // 终止请求(会触发 'abort' 事件)
});
// 处理超时后的错误
req.on('error', (err) => {
if (err.code === 'ECONNRESET') {
console.log('请求被主动终止(超时)');
} else {
console.error('请求错误:', err);
}
});
req.end();
说明:
- 若服务器 3 秒内未返回响应,客户端触发
'timeout'事件,调用req.abort()终止请求,避免无限等待。 - 终止后会触发
'error'事件,错误码为ECONNRESET(连接被重置),需在事件中处理。
三、底层套接字(net.Socket)的超时补充
无论是服务器端的 socket(来自 'connection' 事件)还是客户端请求的 socket(可通过 req.socket 访问),其底层都是 net.Socket 实例,也提供超时控制:
socket.setTimeout(msecs[, callback]):设置套接字的超时时间(与http.Server或http.ClientRequest的超时类似,但更底层)。socket.on('timeout', () => { ... }):套接字超时事件,通常无需单独设置,因为http模块已封装上层超时。
注意:http 模块的超时 API(server.setTimeout、req.setTimeout)本质上是对 net.Socket 超时的封装,优先使用上层 API 更符合 HTTP 场景。
四、超时 API 对比与最佳实践
| 场景 | 核心 API | 超时触发条件 | 处理方式 |
|---|---|---|---|
| 服务器端 | server.setTimeout() | 客户端连接后长时间无数据交互 | 调用 socket.destroy() 关闭连接 |
| 客户端 | req.setTimeout() | 发送请求后长时间未收到服务器响应 | 调用 req.abort() 终止请求 |
最佳实践:
- 服务器端:根据业务设置合理超时(如普通接口 5-10 秒,大文件上传 60 秒以上),超时后必须关闭
socket。 - 客户端:强制设置超时(如 10-30 秒),避免因网络异常导致请求永久挂起,超时后需终止请求并处理错误。
- 区分场景:服务器超时针对 “客户端不活跃”,客户端超时针对 “服务器无响应”,二者需分别设置。
1、服务器端超时设置(防止客户端连接长期无活动)
服务器需要限制客户端连接的最大空闲时间,避免资源浪费。
const http = require('http');
// 创建服务器
const server = http.createServer((req, res) => {
// 模拟处理耗时请求(例如:5秒后响应)
setTimeout(() => {
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('请求处理完成\n');
}, 5000);
});
// 1. 设置服务器连接超时时间(3秒)
// 超过3秒无数据交互则触发超时
server.setTimeout(3000);
// 2. 监听超时事件,主动关闭无效连接
server.on('timeout', (socket) => {
console.log('客户端连接超时,即将关闭连接');
// 关闭底层TCP连接(必须手动调用,否则连接会保持)
socket.destroy(new Error('连接超时:服务器已关闭长时间无活动的连接'));
});
// 3. 监听连接错误(如超时后关闭连接的错误)
server.on('connection', (socket) => {
socket.on('error', (err) => {
console.log('连接错误:', err.message);
});
});
// 启动服务器
server.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
console.log('连接超时设置:3秒(3000ms)');
});
测试方式:
用 curl http://localhost:3000 发起请求,由于服务器处理需要 5 秒,超过 3 秒超时设置,会触发超时并关闭连接,客户端会收到错误。
2、客户端请求超时设置(防止服务器无响应)
客户端需要限制请求的最大等待时间,避免因服务器故障导致无限等待。
const http = require('http');
// 向服务器发送请求(假设服务器处理耗时较长)
const options = {
hostname: 'localhost',
port: 3000,
path: '/',
method: 'GET'
};
const req = http.request(options, (res) => {
console.log(`收到响应,状态码:${res.statusCode}`);
let data = '';
res.on('data', (chunk) => { data += chunk; });
res.on('end', () => {
console.log('响应内容:', data);
});
});
// 1. 设置客户端请求超时时间(4秒)
// 若4秒内未收到服务器响应,则触发超时
req.setTimeout(4000);
// 2. 监听超时事件,主动终止请求
req.on('timeout', () => {
console.log('请求超时(4秒未收到响应),终止请求');
// 终止请求(会触发后续的error事件)
req.abort();
});
// 3. 处理请求错误(包括超时导致的错误)
req.on('error', (err) => {
if (err.code === 'ECONNRESET') {
console.log('请求已被主动终止(超时)');
} else {
console.error('请求错误:', err.message);
}
});
// 发送请求
req.end();
测试方式:
配合上面的服务器代码运行,服务器处理需要 5 秒,客户端设置 4 秒超时,会触发超时并终止请求,输出 “请求超时” 信息。
3、精细化控制:按请求类型设置不同超时
实际业务中,不同接口(如普通接口、文件上传)可能需要不同的超时时间,可在请求处理函数中动态设置。
const http = require('http');
const server = http.createServer((req, res) => {
// 1. 按请求路径动态设置超时
if (req.url === '/upload' && req.method === 'POST') {
// 文件上传允许更长超时(30秒)
req.socket.setTimeout(30000);
console.log('文件上传接口超时设置:30秒');
} else {
// 普通接口超时(5秒)
req.socket.setTimeout(5000);
console.log('普通接口超时设置:5秒');
}
// 2. 监听当前请求的超时事件
req.socket.on('timeout', () => {
console.log(`[${req.url}] 请求超时`);
res.writeHead(408, { 'Content-Type': 'text/plain' }); // 408 Request Timeout
res.end('请求超时:服务器未在规定时间内收到完整请求\n');
req.socket.destroy(); // 关闭连接
});
// 模拟处理请求
setTimeout(() => {
res.end(`[${req.url}] 处理完成\n`);
}, 6000); // 模拟6秒处理时间(会触发普通接口超时)
});
server.listen(3000, () => {
console.log('服务器运行在 http://localhost:3000');
console.log('测试:GET / (5秒超时),POST /upload (30秒超时)');
});
测试方式:
- 访问
http://localhost:3000(普通接口):6 秒处理时间超过 5 秒超时,会返回 408 状态码。 - 发送 POST 请求到
http://localhost:3000/upload:6 秒处理时间未超过 30 秒超时,会正常响应。
4、HTTPS 场景的超时设置(与 HTTP 类似)
https 模块的超时 API 与 http 完全一致,只需替换模块引入即可。
const https = require('https');
const fs = require('fs');
// 证书配置(实际使用时替换为真实证书)
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt')
};
// 创建HTTPS服务器,超时设置与HTTP相同
const server = https.createServer(options, (req, res) => {
res.end('HTTPS 响应\n');
});
// 设置超时(5秒)
server.setTimeout(5000);
server.on('timeout', (socket) => {
console.log('HTTPS连接超时');
socket.destroy();
});
server.listen(443, () => {
console.log('HTTPS服务器运行在 https://localhost');
});
核心总结
- 服务器端:通过
server.setTimeout()或req.socket.setTimeout()设置超时,超时后需调用socket.destroy()关闭连接。 - 客户端:通过
req.setTimeout()设置超时,超时后调用req.abort()终止请求,并在'error'事件中处理ECONNRESET错误。 - 灵活性:可根据请求类型(如接口、文件上传)动态调整超时时间,平衡用户体验与资源利用率。
2991

被折叠的 条评论
为什么被折叠?



