不确定是否应该在这里或其他社区询问(即超级用户或 Unix&Linux)但暂时会留在这里。
我有一个使用 Selenium 并由 PM2 运行时管理的 dockerised NodeJS 应用程序。该应用程序在 DO 框上运行,1GB记忆 &25 GB磁盘。该应用程序只是使用 Selenium WebDriver 每隔 2 分钟定期从网站抓取数据。不久前我遇到了这个问题,如果我通过 SSH 进入该框,任何命令都会返回:
-bash:fork:重试:资源暂时不可用
设置一个新的 DO 框并进行监控以测量内存使用情况。我的使用量正在逐渐增加,所以我以为是某个地方发生了内存泄漏。试图找到它,但找不到(仍在搜索中)。我看到 PM2 有一个选项如果内存使用量达到一定程度,则重新启动应用程序。作为预防措施,我将其设置为800M
(80%)。 我的ecosystem.config.js
:
module.exports = {
apps: [
{
name: 'scraper',
script: './index.js',
watch: process.env.NODE !== 'production',
ignore_watch: ['node_modules', 'logs', 'test', 'scripts', '.vscode', '.git'],
out_file: './logs/app.log',
max_memory_restart: '800M',
node_args: '--expose-gc',
env_development: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
}
}
]
}
再看看周围,我发现PM2 可能导致内存泄漏由于没有彻底运行垃圾收集,所以我加入了节点参数,--expose-gc
以强制每隔一分钟运行一次垃圾收集(基于这个例子):
exports.generateHeapDumpAndStats = function() {
try {
if (global.gc) {
global.gc()
} else {
logger.info('Garbage collection unavailable. Use "--expose-gc" when launching to enable forced garbage collection')
}
const heapUsed = process.memoryUsage().heapUsed
const heapUsedMb = (heapUsed / 1024 * 1024).toFixed(2)
logger.info(`Program is using ${heapUsedMb} MB of heap`)
} catch (err) {
logger.error(`Error: ${err.message}`)
process.exit(1)
}
}
我以为这会很顺利,因为即使垃圾收集失败,PM2 也会以 80% 的使用率重新启动。我大约在晚上10:45 (格林威治标准时间 +1)从我的使用情况图来看,容器切出了@凌晨 2:00。这是我过去 24 小时的使用情况图表:
您可以看到内存使用率甚至还不到 80%,那么我是否应该降低重启阈值作为临时措施?
我试图查看盒子本身的内存使用情况,但我输入的任何命令都会出现上述错误。
值得我尝试设置吗--max_old_space_size
?我已经看到 NodeJS 进程尝试为自己分配 1.5GB 内存,而我在这个盒子上没有。
我很困惑为什么会发生这种情况。遗憾的是,容器的日志仅写入盒子上的本地文件,因此我现在无法访问它们。
我尝试检查正在运行的容器并且它返回了一些有用的信息:
我的npm start
命令是:
sudo -E pm2-runtime --raw Ecosystem.config.js --env production --only scraper
并完成Dockerfile
:
FROM selenium/standalone-chrome
WORKDIR /usr/src/app
RUN curl -sL https://deb.nodesource.com/setup_12.x | sudo -E bash -
RUN sudo apt-get install -y nodejs build-essential firefox
# copy package.json & package-lock.json and install packages
# we do this separate from the application code to better use docker's caching
# `npm install` will be cached on future builds if only the app code changed
COPY package*.json ./
RUN sudo npm install pm2 -g
RUN sudo npm install
# ENV vars dynamically set here by CI
# copy the app
COPY . .
# expose port for express & start
EXPOSE 3000
CMD [ "npm", "start"]
如果需要的话,我会根据要求提供代码,只是最初认为没有必要,也不想让问题变得太大:)
笔记: 我最初在 SO 上发布了这个问题,但被要求将其移到这里
编辑
根据 @dirkt 的评论,看起来我可能达到了资源限制。ulimit -a
返回我:
core file size (blocks, -c) 0
data seg size (kbytes, -d) unlimited
scheduling priority (-e) 0
file size (blocks, -f) unlimited
pending signals (-i) 3842
max locked memory (kbytes, -l) 16384
max memory size (kbytes, -m) unlimited
open files (-n) 1024
pipe size (512 bytes, -p) 8
POSIX message queues (bytes, -q) 819200
real-time priority (-r) 0
stack size (kbytes, -s) 8192
cpu time (seconds, -t) unlimited
max user processes (-u) 3842
virtual memory (kbytes, -v) unlimited
file locks (-x) unlimited
因此,用户有进程限制,我认为这就是我遇到的问题。但是,我不太确定在哪里可以更改此值,我应该将其设置为多少unlimited
还是将其提高到任意值?没有设置限制/etc/security/limits.conf
。我见过几种方法来更改软/硬(ulimit
CLI,,limits.conf
-user.conf
我想后者与我无关,因为我正在运行root
)用户限制。还值得注意的是,我正在以以下方式运行此 docker 容器:root
(将来会改变)