問題:使用node里的log4js,生成了大量的文件句柄且沒有釋放(too many open file),最總導致服務宕機。
需求:按用戶和日期級別生成多個log文件。一天有n個用戶請求,生成n份log。
最初的實現:log4js配置,type:file
const app = express() const log4js = require('log4js') app.post('/userTest', function(req, res) { let expressData = [] let reqData req.on('data', function(data){ expressData.push(data) }) req.on('end', function() { reqData = Json.parse(Buffer.concat(expressData).toString()) })
// 配置log4js
log4js.configure({
appenders: {
console: {
type: 'console' }, userLog: { type: 'File', filename: `logs/${userId}_${(new Date()).format('yyyyMMdd')}.log`, maxLogSize: 1024 * 1024 * 1024, //單個log最大size 1GB alwaysIncludePattern: true, layout: { type: 'pattern', pattern: '%d %p %c %X{userId} %m%n' } } }, categories: { default: {appenders: ['console','userLog'], level: 'info'} }, replaceConsole: true })
let logger = log4js.getLogger('userLog')
logger.addContext('userId', reqData.userId)
// 記錄log
logger.info('just a test')
})
每當執行到log4js.configure時,會生成一個文件句柄,且不會釋放。
看起來寫的很爛,當初自己為什么不把type設成multiFile?
改成multiFile,如下
const app = express() const log4js = require('log4js') // 配置log4js log4js.configure({ appenders: { console: { type: 'console' }, multi: { type: 'multiFile', base: 'logs/', property: 'label', extension: '.log', maxLogSize: 1024*1024*1024 // backup 1GB } }, categories: { default: { appenders: ['console','multi'], level: 'info'} } }) app.post('/userTest', function(req, res) { let expressData = [] let reqData req.on('data', function(data){ expressData.push(data) }) req.on('end', function() { reqData = Json.parse(Buffer.concat(expressData).toString()) }) let logger =log4js.getLogger(`default`) logger.addContext('label',`${reqData.userId}_${new Date().format('yyyyMMdd')}`) // 記錄log logger.info('just a test') })
但是,還是會產生文件句柄,長時間之后還是會宕機。
so。。。上github 啊
how to close multiFile appender file handle #691
https://github.com/log4js-node/log4js-node/issues/691
added timeout support to multiFile appender
https://github.com/log4js-node/log4js-node/commit/13909b6fe39e75f5b83e3019bde685bd19af8a1e
原來只要在配置里面加上timeout,即可
log4js.configure({ appenders: { console: { type: 'console' }, multi: { type: 'multiFile', base: 'log/', property: 'label', extension: '.log', timeout:20, // optional activity timeout in ms after which the file will be closed. maxLogSize: 100*1024*1024 // Backup every 100mb } }, categories: { default: { appenders: ['console','multi'], level: loggerLevel } } })
另外一點需要注意,這個bug是 3 May 2018 修復的,有些版本不支持
所以用最新的吧!!!
生成的文件句柄可以用 ProcessExplorer.exe 查看, 可參考: https://www.cnblogs.com/blplusyan/p/12108612.html