Nodejs log4js 应用到cluster问题

Nodejs log4js 应用到cluster问题

我在express里面使用cluster模块,可以正常使用,加入log4js后抛出异常如下 events.js:72 throw er; // Unhandled ‘error’ event ^ Error: write after end at writeAfterEnd (_stream_writable.js:130:12) at WriteStream.Writable.write (_stream_writable.js:178:5) at writeTheChunk (E:\code\VideoDemo\node_modules\log4js\lib\streams\BaseRollingFileStream.js:51:20) at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:199:13 at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:120:21 at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:196:17 at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:499:34 at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:120:21 at Object.oncomplete (fs.js:107:15) worker 16204 died8


3 回复

Nodejs log4js 应用到cluster问题

在使用Express时,我尝试结合Cluster模块来实现多进程处理。一开始,一切正常,但当我引入了log4js进行日志记录时,却遇到了一个异常错误:

events.js:72
throw er; // Unhandled ‘error’ event
^
Error: write after end
at writeAfterEnd (_stream_writable.js:130:12)
at WriteStream.Writable.write (_stream_writable.js:178:5)
at writeTheChunk (E:\code\VideoDemo\node_modules\log4js\lib\streams\BaseRollingFileStream.js:51:20)
at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:199:13
at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:120:21
at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:196:17
at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:499:34
at E:\code\VideoDemo\node_modules\log4js\node_modules\async\lib\async.js:120:21
at Object.oncomplete (fs.js:107:15)
worker 16204 died8

这个问题主要发生在write after end错误上,通常是因为尝试在一个已结束的流上写入数据。在使用log4js和cluster模块时,这种情况比较常见,因为每个工作进程可能试图同时访问同一个文件。

解决方案

为了解决这个问题,我们需要确保每个工作进程拥有独立的日志文件。可以通过配置log4js,为每个进程创建单独的日志文件来解决。

const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
const log4js = require('log4js');

if (cluster.isMaster) {
  for (let i = 0; i < numCPUs; i++) {
    cluster.fork();
  }
} else {
  // 每个子进程设置独立的日志文件
  log4js.configure({
    appenders: { 
      out: { type: 'file', filename: `logs/${process.pid}.log` } 
    },
    categories: { default: { appenders: ['out'], level: 'debug' } }
  });

  const logger = log4js.getLogger();

  logger.info(`Worker ${process.pid} started`);
  
  // 你的业务逻辑
}

在这个示例中,我们通过process.pid为每个子进程生成唯一的日志文件名。这样,即使所有工作进程都试图写入日志,它们也会被路由到各自的文件,避免冲突。

希望这能帮助你解决遇到的问题!


hello,兄弟,这个问题解决了没有啊?我也遇到这个问题了

当你在使用 cluster 模块时,如果想要使用 log4js 进行日志记录,可能会遇到多进程环境下文件写入的问题。这是因为每个 worker 进程都试图写入同一个日志文件,导致冲突。

解决方案

一种解决方案是为每个 worker 进程设置独立的日志文件,以避免多个进程同时写入同一文件的问题。

示例代码

const cluster = require('cluster');
const http = require('http');
const path = require('path');
const log4js = require('log4js');

// 设置日志配置
log4js.configure({
    appenders: {
        out: { type: 'stdout' },
        file: {
            type: 'file',
            filename: path.join(__dirname, `logs/${cluster.worker.id}.log`)
        }
    },
    categories: {
        default: { appenders: ['out', 'file'], level: 'info' }
    }
});

const logger = log4js.getLogger();

if (cluster.isMaster) {
    const numWorkers = require('os').cpus().length;

    console.log(`Master cluster setting up ${numWorkers} workers...`);

    for (let i = 0; i < numWorkers; i++) {
        cluster.fork();
    }

    cluster.on('exit', (worker, code, signal) => {
        console.log(`Worker ${worker.process.pid} died`);
        cluster.fork();
    });
} else {
    // Worker process
    logger.info(`Worker ${cluster.worker.id} running`);
    http.createServer((req, res) => {
        logger.info(`Request received: ${req.url}`);
        res.writeHead(200);
        res.end('Hello World\n');
    }).listen(8000);

    console.log(`Worker ${cluster.worker.id} started on port 8000`);
}

解释

  1. 日志配置:我们为每个 worker 进程设置了不同的日志文件。filename 中使用了 ${cluster.worker.id} 来确保每个 worker 都有自己的日志文件。
  2. 集群管理:主进程创建指定数量的工作进程,并监听工作进程的退出事件,以便重新启动它们。
  3. 日志记录:每个 worker 进程会使用自己的日志文件进行日志记录,从而避免写入冲突。

这样,每个 worker 都会在各自的日志文件中写入日志信息,解决了多进程写入同一文件导致的问题。

回到顶部