我想知道Log4j2是否已经考虑到这一点,或者是否有可能(崩溃|丢失日志等)以非常高的并发性

时间:2022-07-19 21:48:25

This question has been askedfor log4j but not log4j2: Is it safe to use the same log file by two different appenders

这个问题已经被问到log4j而不是log4j2:两个不同的appender使用相同的日志文件是否安全

Technically, you can create multiple appenders in Log4j2 that write in the same file. This seems to work well.

从技术上讲,您可以在Log4j2中创建多个写入同一文件的appender。这似乎运作良好。

Here's my OS / JDK :

这是我的OS / JDK:

  • Oracle JDK 7u45
  • Oracle JDK 7u45

  • Ubuntu LTE 14.04
  • Ubuntu LTE 14.04

Here's a sample configuration (in yaml) :

这是一个示例配置(在yaml中):

Configuration:
  status: debug

  Appenders:
    RandomAccessFile:
      - name: TestA
        fileName: logs/TEST.log
        PatternLayout:
          Pattern: "%msg%n"
      - name: TestB
        fileName: logs/TEST.log
        PatternLayout:
          Pattern: "%msg%n"

  Loggers:
    Root:
      level: trace
      AppenderRef:
        - ref: TestA
        - ref: TestB

My Java sample :

我的Java示例:

final Logger root = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
root.trace("!!! Trace World !!!");
root.debug("!!! Debug World !!!");
root.info("!!! Info World  !!!");
root.warn("!!! Warn World  !!!");
root.error("!!! Error World !!!");

My log file result :

我的日志文件结果:

20150513T112956,819 TRACE "!!! Trace World !!!"
20150513T112956,819 TRACE "!!! Trace World !!!"
20150513T112956,819 DEBUG "!!! Debug World !!!"
20150513T112956,819 DEBUG "!!! Debug World !!!"
20150513T112956,819 INFO  "!!! Info World  !!!"
20150513T112956,819 INFO  "!!! Info World  !!!"
20150513T112956,819 WARN  "!!! Warn World  !!!"
20150513T112956,819 WARN  "!!! Warn World  !!!"
20150513T112956,819 ERROR "!!! Error World !!!"
20150513T112956,819 ERROR "!!! Error World !!!"

I would like to know if Log4j2 has been built with that in mind or if things may (crash | lose logs | etc) at very high concurrency.

我想知道Log4j2是否已经考虑到这一点,或者如果事情可能(崩溃|丢失日志|等)以非常高的并发性。

UPDATE :

I ran this Benchmark test and there is no missing log. Still, I'm not sure this test fully solves the question. :

我运行了这个Benchmark测试,并没有丢失日志。不过,我不确定这个测试能否完全解决这个问题。 :

public class Benchmark {

    private static final int nbThreads = 32;
    private static final int iterations = 10000;
    static List<BenchmarkThread> benchmarkThreadList = new ArrayList<>(nbThreads);
    private static Logger root;

    static {
        System.setProperty("Log4jContextSelector", "org.apache.logging.log4j.core.async.AsyncLoggerContextSelector");
    }

    public static void main(String[] args) throws InterruptedException {

        root = LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);


        // Create BenchmarkThreads
        for (int i = 1; i <= nbThreads; i++) {
            benchmarkThreadList.add(new BenchmarkThread("T" + i, iterations));
        }

        root.error("-----------------------------------------------------------");
        root.error("----------------------  WARMUP  ---------------------------");
        root.error("-----------------------------------------------------------");

        // Warmup loggers
        doBenchmark("WARMUP", 100);

        Thread.sleep(100);
        root.error("-----------------------------------------------------------");
        root.error("---------------------  BENCHMARK  -------------------------");
        root.error("-----------------------------------------------------------");

        // Execute Benchmark
        for (int i = 0; i < nbThreads; i++) {
            benchmarkThreadList.get(i).start();
        }

        Thread.sleep(100);
        root.error("-----------------------------------------------------------");
        root.error("----------------------  FINISHED  -------------------------");
        root.error("-----------------------------------------------------------");

    }

    protected static void doBenchmark(String name, int iteration) {
        for (int i = 1; i <= iteration; i++) {
            root.error("{};{}", name, i);
        }
    }


    protected static class BenchmarkThread extends Thread {

        protected final int iteration;
        protected final String name;

        public BenchmarkThread(String name, int iteration) {
            this.name = name;
            this.iteration = iteration;
        }

        @Override
        public void run() {
            Benchmark.doBenchmark(name, iteration);
        }
    }

}

1 个解决方案

#1


UPDATE: I did not realize that you are already using Async Loggers. In that case this is indeed a log4j2 question. :-)

更新:我没有意识到你已经在使用异步记录器。在这种情况下,这确实是一个log4j2问题。 :-)

The answer is yes, log4j2 and especially Async Loggers are designed with very high concurrency in mind. Multiple loggers in multiple threads can log concurrently, and the resulting log messages are put on a lock-free queue for later processing by the background thread. There is a single background thread that calls all appenders sequentially, so even if multiple appenders write to the same file, no messages are dropped and messages from each logger thread are written fully before the next message is written (no partial writes).

答案是肯定的,log4j2尤其是异步记录器在设计时考虑到了很高的并发性。多个线程中的多个记录器可以并发记录,并将生成的日志消息放在无锁队列中,以供后续线程稍后处理。有一个后台线程可以顺序调用所有appender,因此即使多个appender写入同一个文件,也不会删除任何消息,并且在写入下一条消息之前会完全写入来自每个记录器线程的消息(不进行部分写入)。

In case of a crash, messages that were in the queue but have not been flushed to disk yet may be lost. This is a trade-off for performance and is the case with all asynchronous logging.

如果发生崩溃,队列中但尚未刷新到磁盘的消息可能会丢失。这是性能的权衡,所有异步日志记录都是如此。

If you are logging synchronously (e.g. without using Async Loggers) it becomes a question of what file I/O atomicity guarantees the JVM and OS make.

如果您正在同步记录(例如,不使用异步记录器),则会成为I / O原子性保证JVM和OS所做的文件的问题。

PREVIOUS ANSWER: This is more of a JVM/OS question than a log4j2 question. Rephrased: if multiple threads concurrently write to the same file, will the resulting file contain all messages (nothing is lost, and all messages are complete and correct)? (You may want to specify your JVM vendor and version and OS name and version.)

以前的答案:这更像是一个JVM / OS问题而不是log4j2问题。重新说明:如果多个线程同时写入同一个文件,生成的文件是否包含所有消息(没有丢失,所有消息都是完整和正确的)? (您可能希望指定JVM供应商和版本以及操作系统名称和版本。)

If you are looking for a safe log4j2 configuration, consider using Async Loggers. With Async Loggers all appenders are called sequentially in the single shared background thread, so you are sure no corruption will occur. In addition you get nice performance benefits.

如果您正在寻找安全的log4j2配置,请考虑使用异步记录器。使用异步记录器,所有appender在单个共享后台线程中按顺序调用,因此您确定不会发生损坏。此外,您还可以获得不错的性能优势

#1


UPDATE: I did not realize that you are already using Async Loggers. In that case this is indeed a log4j2 question. :-)

更新:我没有意识到你已经在使用异步记录器。在这种情况下,这确实是一个log4j2问题。 :-)

The answer is yes, log4j2 and especially Async Loggers are designed with very high concurrency in mind. Multiple loggers in multiple threads can log concurrently, and the resulting log messages are put on a lock-free queue for later processing by the background thread. There is a single background thread that calls all appenders sequentially, so even if multiple appenders write to the same file, no messages are dropped and messages from each logger thread are written fully before the next message is written (no partial writes).

答案是肯定的,log4j2尤其是异步记录器在设计时考虑到了很高的并发性。多个线程中的多个记录器可以并发记录,并将生成的日志消息放在无锁队列中,以供后续线程稍后处理。有一个后台线程可以顺序调用所有appender,因此即使多个appender写入同一个文件,也不会删除任何消息,并且在写入下一条消息之前会完全写入来自每个记录器线程的消息(不进行部分写入)。

In case of a crash, messages that were in the queue but have not been flushed to disk yet may be lost. This is a trade-off for performance and is the case with all asynchronous logging.

如果发生崩溃,队列中但尚未刷新到磁盘的消息可能会丢失。这是性能的权衡,所有异步日志记录都是如此。

If you are logging synchronously (e.g. without using Async Loggers) it becomes a question of what file I/O atomicity guarantees the JVM and OS make.

如果您正在同步记录(例如,不使用异步记录器),则会成为I / O原子性保证JVM和OS所做的文件的问题。

PREVIOUS ANSWER: This is more of a JVM/OS question than a log4j2 question. Rephrased: if multiple threads concurrently write to the same file, will the resulting file contain all messages (nothing is lost, and all messages are complete and correct)? (You may want to specify your JVM vendor and version and OS name and version.)

以前的答案:这更像是一个JVM / OS问题而不是log4j2问题。重新说明:如果多个线程同时写入同一个文件,生成的文件是否包含所有消息(没有丢失,所有消息都是完整和正确的)? (您可能希望指定JVM供应商和版本以及操作系统名称和版本。)

If you are looking for a safe log4j2 configuration, consider using Async Loggers. With Async Loggers all appenders are called sequentially in the single shared background thread, so you are sure no corruption will occur. In addition you get nice performance benefits.

如果您正在寻找安全的log4j2配置,请考虑使用异步记录器。使用异步记录器,所有appender在单个共享后台线程中按顺序调用,因此您确定不会发生损坏。此外,您还可以获得不错的性能优势