【问题标题】:Which Appenders should be used in distributed system? How to configure them?在分布式系统中应该使用哪些 Appender?如何配置它们?
【发布时间】:2012-08-08 11:09:55
【问题描述】:

我正在尝试将日志记录组件添加到分布式系统。它是用AspectJ 编写的,以避免链接当前的源代码。我使用 socket appender 发送日志,但我想尝试一些更有效的方法。

我听说我应该使用JMSAppenderAsyncAppender,但我没有配置它。我应该创建Receiver 来收集日志并将它们传递到数据库和GUI(我使用ChainSaw)吗?

我尝试关注 turorial1tutorial2 ,但它们还不够清楚。

编辑:

在我准备的一个小型演示中,我为一个请求发送了 6 个日志(模拟 3 个组件)

[2012-08-08 15:40:28,957] [request1344433228957] [Component_A] [start]
[2012-08-08 15:40:32,050] [request1344433228957] [Component_B] [start]
[2012-08-08 15:40:32,113] [request1344433228957] [Component_C] [start]
[2012-08-08 15:40:32,113] [request1344433228957] [Component_C] [end - throwing]
[2012-08-08 15:40:32,144] [request1344433228957] [Component_B] [end]
[2012-08-08 15:40:32,175] [request1344433228957] [Component_A] [end]

使用套接字 Appender。所以我的 log4j.properties 是:

log4j.rootLogger=DEBUG, server

log4j.appender.server=org.apache.log4j.net.SocketAppender
log4j.appender.server.Port=4712
log4j.appender.server.RemoteHost=localhost
log4j.appender.server.ReconnectionDelay=1000

所以我跑

>java -classpath log4j-1.2.17.jar org.apache.log4j.net.SimpleSocketServer 4712 log4j-server.properties

有配置

log4j.rootLogger=DEBUG, CA, FA

#
log4j.appender.CA=org.apache.log4j.ConsoleAppender
log4j.appender.CA.layout=org.apache.log4j.PatternLayout
log4j.appender.CA.layout.ConversionPattern=[%d] [%t] [%c] [%m]%n

#
log4j.appender.FA=org.apache.log4j.FileAppender
log4j.appender.FA.File=report.log
log4j.appender.FA.layout=org.apache.log4j.PatternLayout
log4j.appender.FA.layout.ConversionPattern=[%d] [%t] [%c] [%m]%n

然后我将日志从文件发送到 Chainsaw:

这绝对是基本的,但我想学习如何做得更好。首先,我想异步发送日志。然后创建非常简单的接收器,例如可以将日志传递到文件。

我尝试按照上面列出的教程进行操作,但失败了。所以问题是:你能提供一些示例配置吗? Receiver.javalog4.properties 文件的示例?

【问题讨论】:

    标签: java logging log4j apache-chainsaw


    【解决方案1】:

    我会使用 NFS 或 CDFS 并在所有机器上安装一个驱动器。让每个应用程序实例写入不同的文件。无论您使用多少台机器,您都可以在一个目录(或驱动器)中找到所有日志。

    我不会在具有高延迟的全球 WAN 上使用 NFS 或 CDFS,例如> 50 毫秒往返。由于这个原因,我使用了 JMS(但我没有使用 log4j)

    【讨论】:

    • 我需要按请求类型而不是机器名将日志拆分到不同的文件中。有可能吗?
    • 您需要近乎实时地执行此操作,还是可以在夜间处理?每个请求一个文件可能非常低效。如果您正在做一些时间敏感的事情,我不会以任何方式使用 log4j。 ;)
    • 我的想法是:消息由 JMS appender 异步发送到 ReceiverReceiver 选择最长的请求或 50 个请求中的一个,然后将它们传递给 ChainSaw 和数据库。在这种情况下我不应该使用 log4j 吗?我正在寻找一个简单的解决方案
    • 您可以将 log4j 与 JMS 一起使用。在我的情况下,原因我收集这些数据是为了测量请求通过系统的时间以及 log4j 和 JMS 影响结果(减慢它们)如果延迟不是问题,或者您以毫秒为单位测量时间,这不是问题。
    【解决方案2】:

    我的两分钱.. 无论您做什么,请确保您使用异步机制将您的日志传送到接收器,否则它最终会停止您的应用程序。另一点,为了可靠地传递日志,您应该考虑在 appender 本身中内置故障转移机制 - 接收器可能会短时间或长时间离线,如果您关心日志,则肯定需要故障转移。我们已经构建了您描述的similar system(抱歉添加),但如果您愿意,可以使用我们的附加程序(查看downloads),它是免费的并且有源代码。还有一个视频教程。它具有故障转移和灵活的异步机制以及备份回退。

    您应该使用多少个附加程序?每个 jvm 一个 appender 就可以了。配置文件可能应该是每个 jvm,不确定您打算如何实现接收器,无论如何,附加程序需要找到您的接收器,通常至少是主机端口对。关于数据库,我对 RDBMS 的经验非常糟糕(我们正在转向 nosql),但如果你不超过几亿条记录,大多数商业数据库都会付出一些努力。我必须说这不是一项简单的任务,我们花了几年时间来构建您刚刚用几个细长的矩形绘制的商业质量系统:)

    【讨论】:

    • 这并不简单,当然 :) 绝对不适合二年级学生。 LogFaces 看起来很棒,毫无疑问,我会从中受到启发。您的建议非常“高级”,因此我将在一分钟内编辑我的问题以提供更多详细信息。我对我使用的所有技术都是新手,肯定需要支持。
    【解决方案3】:

    我终于找到了如何配置它。我将 2 个文件放入 src 文件夹中。

    jndi.properties

    topic.logTopic=logTopic
    

    和 log4j-jms.properties

    log4j.rootLogger=INFO, stdout, jms
    
    ## Be sure that ActiveMQ messages are not logged to 'jms' appender
    log4j.logger.org.apache.activemq=INFO, stdout
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern= 
    
    ## Configure 'jms' appender. You'll also need jndi.properties file in order to make it work
    log4j.appender.jms=org.apache.log4j.net.JMSAppender
    log4j.appender.jms.InitialContextFactoryName=org.apache.activemq.jndi.ActiveMQInitialContextFactory
    log4j.appender.jms.ProviderURL=tcp://localhost:61616
    log4j.appender.jms.TopicBindingName=logTopic
    log4j.appender.jms.TopicConnectionFactoryBindingName=ConnectionFactory
    

    然后我用 VM 参数运行我的程序

    -Dlog4j.configuration=log4j-jms.properties
    

    Receiver.java类中接收日志

    public class Receiver implements MessageListener {
    
        PrintWriter pw = new PrintWriter("result.log");
        Connection conn;
        Session sess;
        MessageConsumer consumer;
    
        public Receiver() throws Exception {
    
    
            ActiveMQConnectionFactory factory = new ActiveMQConnectionFactory("tcp://localhost:61616");
            Connection conn = factory.createConnection();
            Session sess = conn.createSession(false, Session.AUTO_ACKNOWLEDGE);
            conn.start();
            MessageConsumer consumer = sess.createConsumer(sess.createTopic("logTopic"));
            consumer.setMessageListener(this);
        }
    
        public static void main(String[] args) throws Exception {
            new Receiver();
    
        }
    
        public void onMessage(Message message) {
            try {
                LoggingEvent event = (LoggingEvent) ((ActiveMQObjectMessage) message).getObject();
    
                DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss,SSS"); 
                String nowAsString = df.format(new Date(event.getTimeStamp())); 
    
                pw.println("["+ nowAsString + "]" + 
                        " [" + event.getThreadName()+"]" +
                        " ["+ event.getLoggerName() + "]" +
                        " ["+ event.getMessage()+"]");
                pw.flush();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }
    

    【讨论】:

      【解决方案4】:

      我推荐 syslog 和内置的 syslog appender。使用 TCP 进行可靠的日志记录(可能是 +Asyc 附加程序)或使用 UDP 进行即发即弃的日志记录。 如果你需要,我有一个 rsyslog 配置。

      【讨论】:

      • 使用 syslog appender 的负面影响是您丢失了 log4j 附带的大量结构化信息。如果起点不是 log4j 肯定是一个不错的选择。
      • 同意,现在,3.5 年后,我们不再使用 syslog。 (logback + logentries appender)。
      猜你喜欢
      • 2012-09-27
      • 1970-01-01
      • 1970-01-01
      • 2011-10-07
      • 1970-01-01
      • 2015-11-27
      • 1970-01-01
      • 2011-05-04
      • 1970-01-01
      相关资源
      最近更新 更多