问题:使用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 查看