Java:如何构建可伸缩的作业处理机制

时间:2014-02-12 12:46:30

标签: java multithreading performance concurrency

我需要构建一个作业处理模块,其中作业的传入速率大约为数百万。我有一台多处理器机器来运行这些作业。在我目前的Java解决方案中,我使用Java的ThreadPoolExecutor框架来创建作业队列,LinkedListBlockingQueue,并且线程数等于系统上可用的处理器。当作业队列不断增长时,此设计无法维持传入速率,即使CPU利用率未达到最大值,它也会在几秒钟内报告溢出。 CPU利用率保持在30-40%的范围内。

这意味着大部分时间都在线程争用中消失,其他CPU保持空闲状态。有没有更好的处理作业的方法,以便更好地利用CPU,以便作业队列不会溢出?

4 个答案:

答案 0 :(得分:2)

我建议你先看看Disruptor。这在存储器环缓冲器中提供了高性能。如果消费者无法跟上,那么如果你可以放慢生产者的速度,这种方法效果最好。

如果你需要一个持久或无界的队列,我建议使用Chronicle(我写的)这样做的好处是生产者不会被生产者放慢速度(并且队列完全脱离堆)

这两者都旨在每秒处理数百万条消息。

答案 1 :(得分:1)

您好您可以使用像RabbitMQ这样的排队系统来保存要处理的消息。如果将它与Spring AMQP结合使用,您可以轻松(一行配置)多线程,并且消息将存储在磁盘上,直到它们准备好由您的应用程序处理。

答案 2 :(得分:1)

您的分析可能是错误的。如果CPU忙于切换作业,那么CPU利用率将为100% - CPU为进程计算的任何事情都会计算。

我的猜测是你有I / O可以运行更多的工作。尝试运行4到8倍的CPU线程。

如果结果太慢,请使用Akka which can process 10 million messages in 23 seconds without any special tuning等框架。

如果这还不够,请查看Disruptor

答案 3 :(得分:0)

神奇的图书馆非常诱人,但往往会误导你走向错误的方向并使你的解决方案日复一日变得更加复杂......干扰人LMAX也这么说:)我认为你应该退后一步,了解根本原因作业队列深度。在你的情况下,我认为它是同一类型的消费者,所以我不认为破坏者会有所帮助。 你提到过线程争用。 我建议先试着看看你是否可以减少争用。不确定您的所有作业是否相关,但如果不是,则可以使用队列的某种分配技术并减少不相关的作业争用。然后你需要知道为什么你的消费者很慢。您是否可以通过在消费者中使用ReadWrite锁或NonBlocking集合来改进锁定策略。