javascript - Node.js 应用程序对 http 请求的延迟呈指数增长
问题描述
我有一个带有一个端点的 Express 应用程序,它从请求中获取一个字符串,将带有该字符串的请求发送到另一台服务器并返回响应。它能够很好地处理一些负载,但是一旦我开始启动它,延迟就会开始不受控制地增长并破坏整个应用程序。您可以在下面找到示例图,首先我尝试每分钟处理 60k 个请求,然后我只做了大约 5k,它在吞吐量和延迟方面都非常平滑。
我尝试使用内置https
模块和axios
库,两者都给出完全相同的结果。
我缺少一些设置吗?像最大并发请求或类似的东西。我对 Node 不太熟悉,所以对我所看到的有点困惑,特别是因为它是在完全不同的基础架构上复制的,同时在相同基础架构上的 Java 应用程序能够在没有任何问题的情况下每分钟执行 100k .
这是我用来发送请求的示例代码:
export const callService = axios => async request => {
const params = {
address: request.fullAddress
}
const response = await axios.get('endpoint', {
params
})
return {
result: response.data
}
}
以下是我获取 axios 实例的方法,稍后将其传递给上面的柯里化函数:
const axiosInstance = axios.create({
baseURL: SERVICE_BASE_URL,
timeout: 10000,
})
我确实验证了一旦我删除了这个调用并只是模拟了响应,我可以使用更大的数字而没有延迟问题。
更新
今天用这段简单的代码做了额外的测试,根本没有Express
服务器,只有这段代码。当我使用Array(1000)
(有效地将并发请求计数设置为1000
)时,它工作正常,只需几秒钟即可完成整个操作。但是,如果我尝试将其设置为10000
,那么我会再次开始看到这些问题。可能值得一提的是,我正在使用 Catalina 的 Mac 上执行此操作,但是,当应用程序在 PCF 中运行时,会观察到相同的行为。代码:
const axiosInstance = Axios.create({
baseURL: SERVICE_URL,
httpAgent: new http.Agent({
keepAlive: true
})
})
const params = {
// some query params
}
console.log(Date.now())
Promise.all([...Array(1000).keys()]
.map(() => axiosInstance.get('path', {
params
})))
.then(it => {
console.log(Date.now())
})
更新 2
看起来问题可能与 DNS 查找有关。我注意到,当我执行大量请求时,它会卡住一段时间,然后其中一个请求getaddrinfo ENOTFOUND
失败,然后所有其他请求都因超时而失败。不知道如何解决这个问题
更新 3
设置得更高ulimit
似乎有助于解决上一个问题,但是随着请求数量的增加,所有请求都开始超时。
解决方案
这里的罪魁祸首似乎是您的系统用尽了可用的文件描述符(零星的 DNS 查找失败是这种情况的常见症状)。由于您已经排除了 Express 的相关性,我怀疑这是由于同时发出的出站请求:每个出站 API 调用都将打开一个到远程服务器的套接字(默认文件描述符限制通常为 1000)。
修复取决于您的确切操作系统,但在典型的 Unix 系统上,您可以检查用户进程的可用文件描述符:
ulimit -n
并用这样的方法提升它(或在 StackOverflow 中搜索“提升文件描述符限制”):
sudo ulimit -n 10000
注意:这里还有其他因素在起作用,正如原始问题的评论链中所述,许多不同的问题都会影响系统的吞吐量:内存压力、CPU 节流、劣质 HTTP 库等。
推荐阅读
- php - 使用 PDO 准备语句创建搜索结果会出错
- sql - 如何将一个表中的所有记录作为 XML 数据类型提取到第二个表的另一列
- vb.net - ImageList (VB.Net Winforms) 导致内存不足错误
- pkcs#11 - PKCS#11 C_Encrypt 因 128 位 AES 密钥的错误参数而失败
- java - 32 位 jvm 上的 Java 程序比 64 位慢
- c - MSVS 2017:指针空值检查不正常
- laravel - Laravel Maat 网站/Excel
- hadoop - 找不到 org.apache.hadoop.conf.Configuration
- javascript - 通过调用函数使用 Ajax 调用 rest api
- angular - 如何提供另一个控制值访问器?