所以我们这里说的超时有几种,一种是连接到服务器(连接超时),另一种是在一段时间内没有通过套接字发送或接收数据时发生超时(空闲超时)。
节点套接字有一个套接字超时,可用于综合连接和空闲超时。这可以通过将套接字超时设置为连接超时,然后在连接时将其设置为空闲超时来完成。
示例:
const request = http.request(url, {
timeout: connectTimeout,
});
request.setTimeout(idleTimeout);
之所以有效,是因为选项中的超时时间在创建套接字时立即设置,setTimeout 函数在连接时在套接字上运行!
无论如何,问题是关于如何测试连接超时。好的,让我们先停止空闲超时。我们可以通过一段时间不发送任何数据来简单地测试一下,这会导致超时。检查!
连接超时有点难以测试,首先想到的是我们需要一个连接的地方,它不会出错,但也不能连接。这会导致超时。但是我们到底要如何在节点中模拟呢?
如果我们跳出框框思考一下,那么我们可能会发现这个超时时间大约是连接所需的时间。为什么连接需要这么长时间并不重要。我们只需要延迟连接所需的时间。这不一定是服务器的事情,我们也可以在客户端上做。毕竟这是连接的部分,如果我们可以在那里延迟它,我们可以测试超时。
那么我们怎么能延迟客户端的连接呢?好吧,我们可以使用 DNS 查找。在建立连接之前,会完成 DNS 查找。如果我们只是将其延迟 5 秒左右,我们可以非常轻松地测试连接超时。
这就是代码的样子:
import * as dns from "dns";
import * as http from "http";
const url = new URL("http://localhost:8080");
const request = http.request(url, {
timeout: 3 * 1000, // connect timeout
lookup(hostname, options, callback) {
setTimeout(
() => dns.lookup(hostname, options, callback),
5 * 1000,
);
},
});
request.setTimeout(10 * 1000); // idle timeout
request.addListener("timeout", () => {
const message = !request.socket || request.socket.connecting ?
`connect timeout while connecting to ${url.href}` :
`idle timeout while connected to ${url.href}`;
request.destroy(new Error(message));
});
在我的项目中,我通常使用我注入的代理。然后代理进行延迟查找。像这样:
import * as dns from "dns";
import * as http from "http";
const url = new URL("http://localhost:8080");
const agent = new http.Agent({
lookup(hostname, options, callback) {
setTimeout(
() => dns.lookup(hostname, options, callback),
5 * 1000,
);
},
});
const request = http.request(url, {
timeout: 3 * 1000, // connect timeout
agent,
});
request.setTimeout(10 * 1000); // idle timeout
request.addListener("timeout", () => {
const message = !request.socket || request.socket.connecting ?
`connect timeout while connecting to ${url.href}` :
`idle timeout while connected to ${url.href}`;
request.destroy(new Error(message));
});
编码愉快!