java - 如何让线程停止相互阻塞写入磁盘上的日志文件?

标签 java multithreading logging file-io blocking

我的线程落后于计划,线程转储显示它们都卡在阻塞 IO 中,将日志输出写入硬盘。我的快速修复只是为了减少日志记录,这对于我的 QA 要求来说很容易做到。当然,这不是垂直可扩展的,很快就会成为一个问题。

我考虑过只增加线程数,但我猜瓶颈在于文件争用,如果这样做是错误的,这可能会很糟糕。

我有很多想法,但真的不知道哪些是富有成果的。

  1. 我考虑过增加线程数,但我猜它们遇到了瓶颈,所以这无济于事。这样对吗?如何确定呢? 减少线程数有帮助吗?
  2. 如何分析要写入磁盘的正确线程数?这是写入请求数、每秒写入字节数、每次写入操作字节数的函数,还有什么?
  3. 我能否切换较低级别的设置(文件系统、操作系统等)以减少对文件的锁定,以换取乱序行的可能性?是在我的 Java 应用程序中还是在更低级别?
  4. 我可以分析我的系统或硬盘以确保它不会以某种方式过度工作吗? (含糊不清,但我不在我的领域内)。

所以我的问题是:如何分析以确定可以安全地写入公共(public)文件的正确线程数?哪些变量决定了这一点 - 写入操作数、每秒写入的字节数、每个写入请求的字节数、任何操作系统或硬盘信息。

还有什么方法可以让日志文件更自由地写入?我们对所有内容都加了时间戳,所以如果能减少阻塞,我可以接受少数无序行。

最佳答案

My threads have fallen behind schedule and a thread dump reveals they're all stuck in blocking IO writing log output to hard disk.

通常在这些情况下,我安排一个线程只是 用于日志记录。大多数日志记录类(例如 PrintStream)都是同步的,并且写入/刷新每行输出。通过移动到中央日志记录线程并使用某种 BlockingQueue 来排队要写入的日志消息,您可以使用 BufferedWriter 或类似的东西来限制个人IO 请求。默认缓冲区大小为 8k,但您应该增加该大小。您需要确保在关闭应用程序时正确关闭流。

使用缓冲写入器,您还可以通过 GZIPOutputStream 写入,如果您的日志消息重复很多,这将显着降低您的 IO 要求。

也就是说,如果您输出了太多的调试信息,您可能是 SOL,需要降低日志记录带宽或提高磁盘 IO 速度。优化应用程序后,接下来的步骤包括将日志服务器上的 SSD 转移到 SSD 来处理负载。您也可以尝试将日志消息分发到多个服务器以进行持久化,但本地 SSD 很可能会更快。

为了模拟 SSD 的优势,本地 RAM 磁盘应该让您对增加的 IO 带宽有一个很好的了解。

I thought about increasing the thread count but I'm guessing they're bottlenecked so this won't do anything. Is this correct?

如果您的所有线程都在 IO 中阻塞,那么是的,增加线程数将无济于事。

How do I profile the right # of threads to be writing to disk?

棘手的问题。您将不得不进行一些测试运行。查看您的应用程序的吞吐量,有 10 个线程,有 20 个线程,等等。您正在尝试最大化您在一段时间内处理的整体事务。确保您的测试运行执行几分钟以获得最佳结果。 但是,重要的是要认识到,如果输出过多,单个线程很容易淹没磁盘或网络 IO 流。

Can I toggle a lower-level setting (filesystem, OS, etc.) to reduce locking on a file in exchange for out-of-order lines being possible? Either in my Java application or lower level?

没有。请参阅上面我的缓冲线程编写器。这与(我假设)没有发生的文件锁定无关。这是关于 IO 请求数/秒。

Can I profile my system or hard disk to ensure it's not somehow being overworked? (Vague, but I'm out of my domain here).

如果您受 IO 限制,那么 IO 会减慢您的速度,因此它会“过度工作”。迁移到 SSD 或 RAM 磁盘是一项简单的测试,可以查看您的应用程序运行速度是否更快。

关于java - 如何让线程停止相互阻塞写入磁盘上的日志文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16426203/

相关文章:

python - python日志记录是否刷新每个日志?

java - 如何在 Java 单元测试中模拟接口(interface)?

java - 获取 java.lang.ClassNotFoundException : java:comp/env/jdbc/oracleInstance in java?

java - 为什么 NetBeans IDE 专门使用 import 语句?

java - 如何知道java进程等待了多少时间

multithreading - 在多线程应用程序中使用屏障的真实示例是什么?

具有四核处理器的笔记本电脑中的 Java 多线程

ios - Xcode 6 应用程序崩溃日志

java - Android Studio 中缺少注解处理

azure - 是否需要对 Azure Application Insights 进行补充日志记录?