Nginx反向代理Nodejs – log4js日志IP显示错误(Nodejs相关)

Nginx反向代理Nodejs – log4js日志IP显示错误(Nodejs相关)

alt Nginx反向代理Nodejs – log4js日志IP显示错误

为提高web应用的吞吐量,我们一般都用nginx做负载均衡器,再反向代理到真正的web服务器。像JAVA服务可以做成Nginx+Tomcat, PHP用Nginx+Spawn-fcgi, 当然nodejs服务,我们也可以做相同的架构Ngnix+Node。

我使用nginx+nodejs+log4js时,发现log4js日志的remote_addr项,总是显示127.0.0.1。本文将重点解释如何通过修改log4js的代码,解决这个问题。

我已经提交这个问题到log4js-node的issue https://github.com/nomiddlename/log4js-node/issues/139

文章目录:

配置nginx反向代理 log4js做为web日志输出 log4js日志ip显示错误及修复

请查看博客文章
http://blog.fens.me/nodejs-nginx-log4js/


6 回复

Nginx反向代理Nodejs – log4js日志IP显示错误

为提高Web应用的吞吐量,通常我们会使用Nginx作为负载均衡器,并反向代理到实际的Web服务器。对于Node.js服务,我们同样可以采用这种架构,即Nginx + Node.js。

在使用Nginx + Node.js + log4js时,我发现log4js日志中的remote_addr字段总是显示为127.0.0.1。本文将重点讲解如何通过修改log4js的代码来解决这一问题。

配置Nginx反向代理

首先,确保你的Nginx配置正确地设置了反向代理。以下是一个简单的Nginx配置示例:

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://localhost:3000; # Node.js 应用监听的端口
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

这里的关键设置是:

  • proxy_set_header X-Real-IP $remote_addr;:将客户端的真实IP地址传递给后端的Node.js应用。
  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;:记录客户端的IP地址,以便在多个代理的情况下追踪。

log4js作为Web日志输出

在Node.js应用中,我们需要配置log4js以正确解析这些HTTP头信息。默认情况下,log4js的日志格式可能无法正确识别这些头信息。

你可以通过自定义日志布局来解决这个问题。以下是一个简单的例子:

const log4js = require('log4js');

log4js.configure({
    appenders: { 
        out: { type: 'stdout', layout: { type: 'pattern', pattern: '%d{yyyy-MM-dd hh:mm:ss} %-5p %c - %m%n' } },
        app: { type: 'file', filename: 'logs/app.log', maxLogSize: 10485760, backups: 3, compress: true, layout: { type: 'pattern', pattern: '%d{yyyy-MM-dd hh:mm:ss} %-5p %c - %m%n' } }
    },
    categories: { default: { appenders: ['out', 'app'], level: 'debug' } }
});

const logger = log4js.getLogger();

logger.info(`Request from ${req.headers['x-real-ip'] || req.ip}`);

在这个例子中,我们使用了req.headers['x-real-ip']来获取客户端的真实IP地址。如果X-Real-IP头不存在,则使用req.ip作为备用。

log4js日志IP显示错误及修复

如果你发现req.ip仍然显示为127.0.0.1,这可能是由于Node.js中间件未正确处理代理头信息。你可以使用express框架的trust proxy功能来解决这个问题。

const express = require('express');
const app = express();

// 启用信任代理
app.set('trust proxy', true);

app.use((req, res, next) => {
    logger.info(`Request from ${req.headers['x-real-ip'] || req.ip}`);
    next();
});

app.listen(3000, () => {
    console.log('Server is running on port 3000');
});

通过以上步骤,你应该能够正确地在log4js日志中显示客户端的真实IP地址。如果问题依然存在,建议检查Nginx和Node.js配置是否完全匹配。


Nginx 反向代理配置,设置header的时候是不是没有指定$remote_addr

指定了。估计是log4js框架,还没有考虑到的feature。

自己改一下就OK了。

log4js 在 connect 中使用时, 提供了对外的扩展.

可以自己指定 format 函数. 即 option.format 指向 function.

如果 format 是 function(而不是 string )时, log4js 会使用自定义的 function 生成 string 来记录.

多谢指点,我去试一下。

当你使用Nginx作为反向代理服务器,并且使用log4js记录日志时,可能会遇到日志中的remote_addr字段始终显示为127.0.0.1的问题。这是因为Nginx默认情况下会将原始请求头信息传递给后端的Node.js应用。

要修正这个问题,你需要确保Nginx正确地将客户端的真实IP地址传递给Node.js应用。这可以通过设置Nginx的proxy_set_header指令来实现,具体如下:

配置Nginx

首先,在Nginx的配置文件中添加或修改以下内容:

server {
    listen 80;
    server_name yourdomain.com;

    location / {
        proxy_pass http://localhost:3000; # 假设你的Node.js应用运行在3000端口
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header Host $host;
    }
}

这段配置告诉Nginx在将请求转发给Node.js应用时,附带客户端的真实IP地址(X-Real-IP),以及任何可能存在的转发地址(X-Forwarded-For)。

修改log4js配置

接着,在Node.js应用中,你需要确保log4js能够读取到这些HTTP头信息。你可以通过自定义Layout来实现这一点。假设你已经安装了log4js,你可以创建一个简单的logger:

const log4js = require('log4js');

// 自定义Layout,用于解析X-Real-IP
log4js.addLayout('custom', function (config) {
    return function (level, { pid, hostname }, { xRealIp }) {
        return `${new Date().toISOString()} ${level} [${pid}] (${hostname}) - ${xRealIp ? xRealIp : '127.0.0.1'}: ${arguments[2]}\n`;
    };
});

log4js.configure({
    appenders: { 
        console: { type: 'console' },
        file: { 
            type: 'file', 
            filename: 'logs/app.log',
            layout: { type: 'custom', xRealIp: true }
        } 
    },
    categories: { default: { appenders: ['console', 'file'], level: 'debug' } }
});

const logger = log4js.getLogger();

// 在中间件中获取并传递X-Real-IP
app.use((req, res, next) => {
    const xRealIp = req.headers['x-real-ip'] || req.ip;
    res.set('x-real-ip', xRealIp);
    next();
});

// 使用logger
logger.info('This is an info message');

这段代码中,我们在自定义Layout中增加了对X-Real-IP的支持,并在中间件中设置了res.set('x-real-ip', xRealIp),这样可以在日志中正确地显示客户端的真实IP地址。

回到顶部