4

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

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

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

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

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

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

4

1 回答 1

8

我的线程落后于计划,线程转储显示它们都被阻塞在阻塞 IO 将日志输出写入硬盘。

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

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

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

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

我考虑过增加线程数,但我猜他们会遇到瓶颈,所以这不会做任何事情。这个对吗?

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

如何分析要写入磁盘的正确线程数?

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

我可以切换较低级别的设置(文件系统、操作系统等)以减少对文件的锁定以换取乱序行吗?在我的 Java 应用程序中还是更低级别?

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

我可以分析我的系统或硬盘以确保它不会以某种方式过度工作吗?(含糊不清,但我不在我的领域)。

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

于 2013-05-07T18:46:02.780 回答