Не уверен, стоит ли спрашивать об этом здесь или в других сообществах.(т.е. SuperUser или Unix&Linux)но пока останусь здесь.
У меня есть докеризованное приложение NodeJS, использующее Selenium и управляемое средой выполнения PM2. Приложение работает на коробке DO с1ГБОбъем памяти &25ГБДиск. Приложение просто периодически извлекает данные с веб-сайта с интервалом в 2 минуты с помощью Selenium WebDriver. Я столкнулся с этой проблемой некоторое время назад, когда при подключении по SSH к ящику любая команда выдавала:
-bash: fork: retry: Ресурс временно недоступен
Настройте новый DO box с мониторингом для измерения использования памяти. У меня использование росло, поэтому я подумал, что где-то есть утечка памяти. Пытался найти ее, но не смог(еще ищете). Я видел, что 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 вечера (GMT+1)& судя по моему графику использования, контейнер вырезан @2:00 утра. Вот графики моего использования за последние 24 часа:
Вы видите, что использование памяти даже близко не приближается к 80%. Может, мне стоит снизить порог перезапуска в качестве временной меры?
Я попытался посмотреть использование памяти на самом устройстве, но любая введенная мной команда выдает указанную выше ошибку.
Стоит ли мне попытаться установить --max_old_space_size
? Я видел, что процесс NodeJS пытается выделить себе 1,5 ГБ памяти, которой у меня нет на этом компьютере.
Я очень озадачен, почему это происходит. К сожалению, логи контейнера записываются только в локальный файл на коробке, поэтому сейчас я не могу получить к ним доступ.
Я попытался проверить запущенные контейнеры, и однажды он выдал что-то полезное:
Моя npm start
команда:
sudo -E pm2-runtime --raw экосистема.config.js --env производство --only скребок
И завершите 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
. Я видел несколько способов изменить soft/hard( ulimit
CLI, limits.conf
, user.conf
- я полагаю, что последнее не имеет для меня значения, поскольку я баллотируюсь как root
)ограничения для пользователя. Также стоит отметить, что я запускаю этот docker-контейнер какroot
(в будущем это изменится)