여기나 다른 커뮤니티에 물어보실지는 모르겠지만(예: 수퍼유저 또는 Unix&Linux)하지만 지금은 여기에 보관할 예정입니다.
Selenium을 사용하고 PM2 런타임으로 관리되는 Dockerised NodeJS 앱이 있습니다. 앱은 다음과 같이 DO 상자에서 실행됩니다.1GB메모리 &25GB디스크. 이 앱은 Selenium WebDriver를 사용하여 2분 간격으로 웹사이트에서 주기적으로 데이터를 긁어내는 것입니다. 얼마 전에 이 문제를 발견했는데 상자에 SSH를 연결하면 모든 명령이 다시 실행됩니다.
-bash: 포크: 재시도: 리소스를 일시적으로 사용할 수 없습니다.
메모리 사용량을 측정하기 위해 모니터링 기능이 있는 새로운 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
1분 간격으로 강제로 가비지 수집을 실행하도록 노드 인수를 포함시켰습니다.(기준으로이 예):
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시. 지난 24시간 동안의 사용량 그래프는 다음과 같습니다.
메모리 사용량이 80%에도 미치지 못하는 것을 볼 수 있는데 임시 조치로 다시 시작 임계값을 낮춰야 합니까?
상자 자체의 메모리 사용량을 보려고 했지만 내가 입력하는 모든 명령에서 위의 오류가 발생합니다.
설정해 볼 가치가 있나요 --max_old_space_size
? 나는 NodeJS 프로세스가 이 상자에 없는 1.5GB의 메모리를 스스로 할당하려고 시도하는 것을 보았습니다.
왜 이런 일이 일어나는지 매우 혼란스럽습니다. 안타깝게도 컨테이너의 로그는 상자의 로컬 파일에만 기록되므로 지금은 액세스할 수 없습니다.
실행 중인 컨테이너를 확인하려고 시도했는데 유용한 내용이 한 번 뱉어졌습니다.
내 npm start
명령은 다음과 같습니다
sudo -E pm2-runtime --raw 생태계.config.js --env 프로덕션 --전용 스크레이퍼
그리고 완료하세요 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
.)사용자에 대한 제한. 이 도커 컨테이너를 다음과 같이 실행하고 있다는 점도 주목할 가치가 있습니다.root
(나중에는 바뀔 예정)