log4j实现日志集中存储
先描述一下问题,多个服务器实现的负载均衡,每个服务器存储在自己的硬盘里。但是现在需要对日志做统一的分析,在多个服务器上统计就麻烦了。思路是把日志统一到一台日志服务器上,再统一做统计分析。怎么统一到一台服务器上,说实话没有特别好的思路,最后尝试了log4j的SocketAppender。查了不少网络资源,都说的有些不明了,还是得亲自尝试之后才见分晓。
1、客户端的配置:
客户端的配置比较简单,只需要告诉log4j需要监听哪个远程服务器的哪个端口即可。直接在log4j.properties里直接配置就好。
log4j.appender.logs=org.apache.log4j.DailyRollingFileAppender
log4j.appender.logs.File = /data/logs/request/logs.log
log4j.appender.logs.layout = org.apache.log4j.PatternLayout
log4j.appender.logs.layout.ConversionPattern=%d [%t] - %m%n
log4j.appender.logs.DatePattern='.'yyyy-MM-dd'.log'
log4j.appender.socket=org.apache.log4j.net.SocketAppender
log4j.appender.socket.RemoteHost=172.16.2.152
log4j.appender.socket.Port=4560
log4j.appender.socket.LocationInfo=true
#下面这两句感觉没用
log4j.appender.socket.layout=org.apache.log4j.PatternLayout
log4j.appender.socket.layout.ConversionPattern=[%-5p] %d{yyyy-MM-dd HH:mm:ss,SSS} method:%l%n%t%m%n
#将日志写入本地和远程日志服务器
log4j.logger.com.test.core.filter =DEBUG,socket,logs
2、日志服务器的配置:
日志服务器需要单独启动一个java进程,接收客户端给自己发送的socket请求。Log4j提供了org.apache.log4j.net.SocketServer类,直接运行其main函数就行了(当然也可以自己写啦)。
java -cp /log4jsocket/serverConfig/log4j-1.2.16.jarorg.apache.log4j.net.SocketServer 4560 /log4jsocket/log4jserver.properties /log4jsocket/clientConfig
/log4jsocket/serverConfig/log4j-1.2.16.jar是log4j jar包存放的位置,org.apache.log4j.net.SocketServer需要三个参数:
1)4560是监听的端口号
2)/log4jsocket/log4jserver.properties是记录日志服务器的日志的配置文件
3)/log4jsocket/clientConfig是客户端配置文件所在的目录(注意是目录)。
着重说一下org.apache.log4j.net.SocketServer的第三个参数,这个文件夹下配置的是各个客户端的日志的配置。配置文件以.lcf结尾,文件名可以用客户端的IP命名,log4j会自己找发送请求的客户端IP对应的那个配置文件,如172.16.2.46服务器发送的socket请求会寻找172.16.2.46.lcf配置文件,并根据配置将日志写入对应的文件。
#注意logger后面的值要与client的值相同
log4j.logger.com.test.core.filter=DEBUG,localLogs
log4j.appender.localLogs=org.apache.log4j.DailyRollingFileAppender
log4j.appender.localLogs.File=/data/logs/request/172.16.2.46/logs.log
log4j.appender.localLogs.layout=org.apache.log4j.PatternLayout
log4j.appender.localLogs.layout.ConversionPattern=%d [%t] - %m%n
log4j.appender.localLogs.DatePattern='.'yyyy-MM-dd'.log'
这样做的好处是可以根据不同客户端,将日志写入不同的文件夹下的。
其实,配置过程就这么简单,但是当你这么做之后,你会发现运行org.apache.log4j.net.SocketServer后,客户端向日志服务器发送请求时,会报找不到.lcf文件的错误,得不到想要的结果。原因出在org.apache.log4j.net.SocketServer代码中的一个小bug。
LoggerRepository configureHierarchy(InetAddress inetAddress)
{
cat.info("Locating configuration file for " + inetAddress);
String s = inetAddress.toString();
int i = s.indexOf("/");
if (i == -1) {
cat.warn("Could not parse the inetAddress [" + inetAddress + "]. Using default hierarchy.");
return genericHierarchy();
}
String key = s.substring(0,i);
File configFile = new File(this.dir, key + CONFIG_FILE_EXT);
if (configFile.exists()) {
Hierarchy h = new Hierarchy(new RootLogger(Level.DEBUG));
this.hierarchyMap.put(inetAddress, h);
new PropertyConfigurator().doConfigure(configFile.getAbsolutePath(), h);
return h;
}
cat.warn("Could not find config file [" + configFile + "].");
return genericHierarchy();
}
String key = s.substring(0, i);换成String key = s.substring(i+1);就好了。这段代码是解析IP地址,然后寻找对应IP命名的.lcf配置文件;如果找不到,则解析默认的generic.lcf。由于截取的错误,导致找不到172.16.2.46.lcf,文件夹下又没有generic.lcf,所以会抛异常。
org.apache.log4j.net.SocketServer代码中的另外一个bug是,只能接收来自一台客户端的日志请求,一旦客户端停止运行,SocketServer也将关闭。查看代码:
public static void main(String[] argv) { if (argv.length == 3) init(argv[0], argv[1], argv[2]); else usage("Wrong number of arguments."); try { cat.info("Listening on port " + port); ServerSocket serverSocket = new ServerSocket(port); cat.info("Waiting to accept a new client."); Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); cat.info("Connected to client at " + inetAddress); LoggerRepository h = (LoggerRepository)server.hierarchyMap.get(inetAddress); if (h == null) { h = server.configureHierarchy(inetAddress); } cat.info("Starting new socket node."); new Thread(new SocketNode(socket, h)).start(); } catch (Exception e) { e.printStackTrace(); } }
问题出在只建立了一个socket连接就不在accept了,加上while循环问题就解决了。
ServerSocket serverSocket = new ServerSocket(port); while(true){ cat.info("Waiting to accept a new client."); Socket socket = serverSocket.accept(); InetAddress inetAddress = socket.getInetAddress(); cat.info("Connected to client at " + inetAddress); LoggerRepository h = (LoggerRepository)server.hierarchyMap.get(inetAddress); if (h == null) { h = server.configureHierarchy(inetAddress); } cat.info("Starting new socket node."); new Thread(new SocketNode(socket, h)).start(); }
好了。Log4j的配置到此结束。
最后一个问题,日志服务器是linux,需要有一个统一的start、shutdown命令来启动和关闭org.apache.log4j.net.SocketServer。那就需要些shell命令了,下面这段代码参考了http://www.cnblogs.com/baibaluo/archive/2011/08/31/2160934.html
catalina.sh
#!/bin/bash
#端口
LISTEN_PORT=4560
#服务端log4j配置文件
SERVER_CONFIG=/log4jsocket/server.properties
#客户端的配置
CLIENT_CONFIG_DIR=/log4jsocket/clientConfig
#Java程序所在的目录(classes的上一级目录)
APP_HOME=/opt/log4jsocket/serverConfig
#需要启动的Java主程序(main方法类)
APP_MAINCLASS=org.apache.log4j.net.SocketServer
#拼凑完整的classpath参数,包括指定lib目录下所有的jar
CLASSPATH=$APP_HOME
for i in "$APP_HOME"/*.jar; do
CLASSPATH="$CLASSPATH":"$i"
done
#JDK所在路径
JAVA_HOME="/opt/jdk1.6.0_30"
#执行程序启动所使用的系统用户,考虑到安全,推荐不使用root帐号
RUNNING_USER=root
#java虚拟机启动参数
JAVA_OPTS="-ms512m -mx512m -Xmn256m -Djava.awt.headless=true -XX:MaxPermSize=128m"
#初始化psid变量(全局)
psid=0
checkpid() {
javaps=`$JAVA_HOME/bin/jps -l | grep $APP_MAINCLASS`
if [ -n "$javaps" ]; then
psid=`echo $javaps | awk '{print $1}'`
else
psid=0
fi
}
start() {
checkpid
if [ $psid -ne 0 ]; then
echo "================================"
echo "warn: $APP_MAINCLASS already started! (pid=$psid)"
echo "================================"
else
echo -n "Starting $APP_MAINCLASS ..."
JAVA_CMD="nohup $JAVA_HOME/bin/java -classpath $CLASSPATH $APP_MAINCLASS $LISTEN_PORT $SERVER_CONFIG $CLIENT_CONFIG_DIR >/dev/null 2>&1 &"
su - $RUNNING_USER -c "$JAVA_CMD"
checkpid
if [ $psid -ne 0 ]; then
echo "(pid=$psid) [OK]"
else
echo "[Failed]"
fi
fi
}
stop() {
checkpid
if [ $psid -ne 0 ]; then
echo -n "Stopping $APP_MAINCLASS ...(pid=$psid) "
su - $RUNNING_USER -c "kill -9 $psid"
if [ $? -eq 0 ]; then
echo "[OK]"
else
echo "[Failed]"
fi
checkpid
if [ $psid -ne 0 ]; then
stop
fi
else
echo "================================"
echo "warn: $APP_MAINCLASS is not running"
echo "================================"
fi
}
status() {
checkpid
if [ $psid -ne 0 ]; then
echo "$APP_MAINCLASS is running! (pid=$psid)"
else
echo "$APP_MAINCLASS is not running"
fi
}
info() {
echo "System Information:"
echo "****************************"
echo `head -n 1 /etc/issue`
echo `uname -a`
echo
echo "JAVA_HOME=$JAVA_HOME"
echo `$JAVA_HOME/bin/java -version`
echo
echo "APP_HOME=$APP_HOME"
echo "APP_MAINCLASS=$APP_MAINCLASS"
echo "****************************"
}
case "$1" in
'start')
start
;;
'stop')
stop
;;
'restart')
stop
start
;;
'status')
status
;;
'info')
info
;;
*)
echo "Usage: $0 {start|stop|restart|status|info}"
exit 0
esac
startup.sh
#!/bin/sh
EXECUTABLE=/log4jsocket/catalina.sh
exec "$EXECUTABLE" start "$@"
shutdown.sh
EXECUTABLE=/log4jsocket/catalina.sh
exec "$EXECUTABLE" stop "$@"
相关推荐
本主题将深入探讨如何使用Apache Kafka和Log4j来实现日志的集中管理和处理。Kafka是一个高吞吐量、分布式的消息发布订阅系统,而Log4j则是一款广泛使用的Java日志框架,二者结合能有效提升日志处理效率和分析能力。 ...
### Log4j 日志信息存储到数据库中的配置与使用 #### 概述 在软件开发过程中,日志记录是至关重要的环节之一。它不仅能够帮助开发者追踪程序运行时的状态,还可以在系统出现故障时提供诊断信息。Apache Log4j 是一...
本文将详细讨论“决对可用,log4j日志集中处理扩展(含server与client)”这一资源所涉及的知识点,包括日志集中处理的概念、Log4j的工作原理、日志服务器和客户端的实现,以及如何将这些元素整合到实际项目中。...
本篇将详细介绍如何利用Log4j将应用日志输出到Flume,以便进行集中管理和分析。 首先,Log4j是一款Java日志框架,它提供了灵活的日志记录功能,允许开发者根据需求定制日志级别、格式和输出目的地。Log4j的配置文件...
4. **日志监控**:使用工具(如Logstash、Fluentd等)收集、解析并转发日志,实现集中式日志管理和分析。 5. **性能优化**:避免在高并发场景下频繁地写入日志,可以使用异步日志记录或日志缓冲机制来提高性能。 ...
本文将深入探讨如何进行`log4j`的源码二次开发,实现通过`DatagramSocket`发送日志消息,以及如何构建一个集中式的日志中心来收集和处理来自多个应用或模块的日志信息。 首先,我们需要了解`log4j`的基本架构。`log...
通过以上步骤,你可以实现将Java应用程序的日志通过log4j2直接输出到MongoDB存储。这个过程不仅方便了日志的管理和分析,也为监控和故障排查提供了便利。在实际项目中,还可以结合其他工具,如ELK(Elasticsearch、...
Log4j是Apache的一个开源项目,它提供了一个灵活的日志框架,允许开发者在Java应用程序中进行日志记录。这个框架的目标是使日志输出更加标准化,提高可读性、可维护性和性能,同时还能根据需要调整日志级别,适应...
《log4j日志记录:理解Exception的处理与优化》 在Java开发中,日志记录扮演着至关重要的角色,它不仅帮助我们追踪程序运行时的状态,还为故障排查提供了宝贵的线索。Log4j作为一款广泛应用的日志框架,其对于异常...
本文将详细探讨如何在Android项目中集成并使用log4j,以及如何实现日志的远程上传。 1. **log4j简介** - Log4j是Apache的一个开源项目,提供了一套灵活的日志记录系统,允许开发者定义不同的日志级别(如DEBUG、...
标题“log4j 涉及的jar包”指的是与log4j日志框架相关的Java档案库文件(JAR文件)。在Java开发中,JAR文件是将多个类文件打包在一起的容器,便于管理和分发。log4j是一个广泛使用的开源日志记录框架,它为应用程序...
本篇将详细介绍如何配置Log4j来将日志信息存储到MySQL数据库中,以实现日志的集中管理和分析。 首先,我们需要了解Log4j的基本结构。Log4j主要由三个组件构成:Logger(日志器)、Appender(输出端)和Layout(布局...
此外,源码阅读也有助于扩展log4j的功能,例如创建新的Appender类型,以适应特定的存储需求。 在实际应用中,log4j-1.2.15不仅可以用作开发中的调试工具,还可以用于生产环境的监控。通过合理配置,可以在不增加...
Log4j是Apache组织开发的一款广泛使用的Java日志框架,它的全名是Apache Log4j 2。这个压缩包文件包含的是Log4j的官方源码,对于开发者来说,能够直接导入到Eclipse中进行学习和研究,或者进行二次开发,具有很高的...
Log4j支持层级结构的记录器,便于实现日志的集中管理和策略继承。 2. **输出源(Appender)**:指定了日志信息的具体输出位置。Log4j提供了丰富的输出源类型,满足不同场景下的日志存储需求。 3. **布局(Layout)...
因此,本文将深入探讨如何利用数据库对Log4j日志进行高效管理,特别是通过DBCP(Database Connection Pooling)和MySQL数据库的结合,实现日志的集中式存储和查询,同时添加用户名等附加信息,增强日志的可追溯性和...
此外,还有许多第三方工具如Logstash、Graylog等可以与log4j配合,实现日志的集中管理和分析,提升运维效率。 7. **安全性考量** 虽然log4j-1.2.8版本相对老旧,但值得注意的是,旧版本可能存在安全风险。例如,...
《log4j2+kafka:构建高效日志流处理系统》 在现代的分布式系统中,日志管理和分析是至关重要的。Log4j2作为Java领域广泛应用的日志框架,提供了强大的日志记录功能,而Kafka作为一个高吞吐量、低延迟的分布式消息...
同时,log4j还可以与其他日志系统集成,如syslog、Flume或Kafka,实现日志的集中管理和分析。 安全是日志管理的另一大挑战。log4j手册中会讲解如何避免日志中的敏感信息泄露,以及如何防止恶意利用日志系统进行攻击...
**日志框架Log4j详解** Log4j是Java领域广泛应用的一个开源日志记录工具,由Apache软件基金会开发。它的核心功能在于提供了一种灵活且高效的方式来记录应用程序运行过程中的事件,这对于调试、性能监控、故障排查...