Nodejs压测出现 no such file or directory, scandir 'XXX'

一个基于 next.js 的项目使用 JMeter 在 docker 容器中进行压力测试,当并发数过高时,会出现以下错误,但该目录确实是存在的,并且随着并发数变高报错也变多。正常访问就不会出现。

错误出现的代码在此: https://github.com/i18next/next-i18next/blob/205e9a4fe5d5d1baca9f5a82561096b6372e1432/src/config/createConfig.ts#L211

2023-12-25 07:47 +00:00: Error: ENOENT: no such file or directory, scandir '/app/packages/eshop/public/locales/cn'
    at Object.readdirSync (node:fs:1405:3)
    at getLocaleNamespaces (/app/node_modules/next-i18next/dist/commonjs/config/createConfig.js:214:16)
    at /app/node_modules/next-i18next/dist/commonjs/config/createConfig.js:231:20
    at Array.map (<anonymous>)
    at getNamespaces (/app/node_modules/next-i18next/dist/commonjs/config/createConfig.js:230:44)
    at createConfig (/app/node_modules/next-i18next/dist/commonjs/config/createConfig.js:271:29)
    at _callee$ (/app/node_modules/next-i18next/dist/commonjs/serverSideTranslations.js:201:53)
    at tryCatch (/app/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:44:17)
    at Generator.<anonymous> (/app/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:125:22)
    at Generator.next (/app/node_modules/@babel/runtime/helpers/regeneratorRuntime.js:69:21) {
  errno: -2,
  syscall: 'scandir',
  path: '/app/packages/eshop/public/locales/cn'
}

报错指向的是用的一个 next.js 的多语言库 next-i18next ,它在每次页面刷新的时候都会调用 fs.readdirSync 读取本地多语言 json 文件。

我也试过在容器里面大量调用(定时器模拟) fs.readdirSync 也没出现报错。

实在不知道是什么原因引起的...有了解的小伙伴吗?


Nodejs压测出现 no such file or directory, scandir 'XXX'
13 回复

我也遇到过,不知道什么原因,感觉是 I/O 句柄被耗尽了。


如果是这种情况有什么工具可以监测到吗?

试试把资源一起打包到 docker ,不要挂载上去
如果要是 docker 在 windows 上的话,那就是 windows 锅

不太理解,能具体说下打包上去和挂载上去区别么?

宿主机的 ulimit -a 返回啥?尝试设置一下? ulimit -n 100000
另外,docker 的参数尝试加下
docker run --ulimit nofile=262144:262144

如果资源内容不变,不需要每次都读,可以做个缓存。

docker 默认是没 ulimit ,可以打开无限的 I/O 句柄,不会主动释放,耗尽主机的 I/O 句柄。
shell<br> grep 'Limit' /lib/systemd/system/docker.service <br># Note that StartLimit* options were moved from "Service" to "Unit" in systemd 229.<br>StartLimitBurst=3<br># Note that StartLimitInterval was renamed to StartLimitIntervalSec in systemd 230.<br>StartLimitInterval=60s<br># Having non-zero Limit*s causes performance problems due to accounting overhead<br>LimitNOFILE=infinity<br>LimitNPROC=infinity<br>LimitCORE=infinity<br>

但是主机内是有 ulimit ,可以分配给 docker 的 I/O 句柄是有限。

shell<br> ulimit -n<br>1024<br>
1 调高主机的 ulimit ,2 限制 docker 的 ulimit

理论是这样,不过就得改这个第三方库了

在 wsl 下使用 await fs.readdir 读取文件过多的文件夹时候也遇到过。。。
怀疑是某种 os 内置的超时。。。
因为没当回事所以没试过修改 ulimit 。。。

是不是用了 inotify 功能啊?这个也是有限的

既然可以主动触发错误,那我建议挂个 strace 看看

怎么看 inotify 有没有启动?

“启动”这个词不太合适
建议你挂上 strace 看看

针对你提到的Node.js压测中出现的“no such file or directory, scandir ‘XXX’”错误,这通常意味着Node.js进程试图访问一个不存在的目录。以下是一些可能的解决步骤和代码示例,帮助你定位并解决问题:

  1. 检查目录路径: 确保你的代码中引用的目录路径是正确的。如果路径是硬编码的,检查是否有拼写错误或路径结构变化。

  2. 动态路径处理: 如果路径是动态生成的,确保生成逻辑正确。例如,使用path模块来处理路径:

    const path = require('path');
    const dirPath = path.join(__dirname, 'relative', 'path', 'to', 'directory');
    
    try {
        const files = fs.readdirSync(dirPath);
        console.log(files);
    } catch (err) {
        console.error('Error reading directory:', err);
    }
  3. 权限问题: 确保Node.js进程有权限访问目标目录。你可以检查目录的权限,或使用更高权限运行Node.js(如使用sudo)。

  4. 目录存在性检查: 在尝试读取目录之前,先检查目录是否存在:

    const fs = require('fs');
    const dirPath = 'path/to/directory';
    
    if (fs.existsSync(dirPath) && fs.statSync(dirPath).isDirectory()) {
        // 目录存在且是目录,执行读取操作
    } else {
        console.error('Directory does not exist or is not a directory:', dirPath);
    }

通过上述步骤,你应该能够定位并解决“no such file or directory, scandir ‘XXX’”的问题。如果问题依旧存在,请检查更详细的日志信息或系统环境配置。

回到顶部
AI 助手
你好,我是IT营的 AI 助手
您可以尝试点击下方的快捷入口开启体验!