不確定是在這裡還是其他社區問這個問題(即超級用戶或 Unix&Linux)但暫時留在這裡。
我有一個使用 Selenium 的 Dockerized NodeJS 應用程序,並由 PM2 運行時管理。該應用程式在 DO 盒上運行1GB記憶 &25GB磁碟.該應用程式只是使用 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
(將來會改變)