【问题标题】:Logging framework with performance in mind考虑性能的日志记录框架
【发布时间】:2018-07-28 23:29:23
【问题描述】:

我想设计一个日志框架,一个强调性能的简单框架。

现在,如果一个应用程序有多个线程(比如一次有 1000 个线程),并且如果我们这样编写代码:

MyLogger logger; // Assuming singleton logger for the entire application

当一个线程想登录文件时,可能有多个线程也想登录,所以我想到了这个同步:

synchronized(logger) {
    // thread does the logging into file
}

但这种方法效率不高,因为它强制执行顺序访问。

我读到了java.util.concurrent.*,我希望这能有所帮助,我看到我们有锁概念lock.tryLock(),但即便如此这也无济于事。

有没有其他方法可以让多个线程写入日志文件而不影响彼此写入文件的数据?

【问题讨论】:

  • 您可能想考虑不编写自己的,而只是使用现有的日志框架之一。如果您决定自己编写,那么也许您应该看看其他开源日志框架如何解决这个问题。无论如何,虽然这是一个有趣的问题,但这可能太宽泛了。
  • @MarkRotteveel:感谢您的回复,但是框架(如 log4J)如何表现得非常好?我正在寻找这些点的输入。有什么可以分享的吗?
  • Log4j 是开源的,如果你想知道,你需要研究它们的源代码。

标签: java multithreading java.util.concurrent


【解决方案1】:

我会让 logger 成为一个类,它有一个待记录项目的队列。当一个类使用这个记录器时,logger.error 我会将内容添加到日志队列中。

Logger 类也应该有自己的线程等待将项目添加到队列中,当添加项目时,它应该从队列中弹出该项目并将其记录到文件中。 (您可以在此处使用发布-订阅)。队列应该像BlockingQueue 变体一样是线程安全的。如果您不只是记录字符串(或不可变对象),您还必须确保传递给 log 方法的对象不应更改(您可能必须在添加到队列之前克隆它)。如果你选择克隆路径,你要考虑不要快速填满内存。

如果你可以使用外部库 log4j2 具有异步日志能力,应该会提供很好的性能。

【讨论】:

    【解决方案2】:

    最后,不管你在java代码中同步线程和访问logger的方式,你仍然存在将所有日志语句写入同一个文件的物理瓶颈,只能顺序完成。

    解决方案是使用发布/订阅机制,其中日志调用仅将日志语句发布到公共队列中。语句由单个线程写入日志文件,该线程使用队列中的语句。

    这样,您只需在将元素放入队列的过程中同步调用线程,这是一种快速且成本低廉的操作。您不希望在写入文件时同步线程,这会慢得多并且会导致更高的开销。

    【讨论】:

      【解决方案3】:

      不使用锁并在锁内执行 I/O 操作会提高性能。在我看来,创建一个缓冲区,所有日志消息都将存储到该缓冲区,一个单独的线程将逐批处理。这里也同时将多个放入队列我们需要同步的线程。我想到的一个优化是分区。对队列进行分区并计算线程的哈希值总是分配给同一个队列。这里我们维护单线程的顺序。如果你想要每个日志的顺序,那么在创建时使用时间戳.Writer 守护程序将从队列池中的所有队列中收集所有日志数据。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-02-21
        • 2012-07-25
        相关资源
        最近更新 更多