Nginx反向代理Nodejs – log4js日志IP显示错误(Nodejs相关)
Nginx反向代理Nodejs – log4js日志IP显示错误(Nodejs相关)
为提高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显示错误及修复
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地址。