如何处理客户端中的大量线程
常见问题解答 > 使用 Apache ActiveMQ Classic > 如何处理客户端中的大量线程
如果您研究 ActiveMQ Classic 客户端中的线程分配,您会注意到默认情况下,每个会话都会分配一个线程。这基本上意味着会话将使用其 ThreadPoolExecutor 来执行其任务。直到版本 5.7,此执行器是无界的,这可能会导致在同一个 JVM 中存在大量繁忙会话的罕见情况下出现 OOM 问题,从而导致线程创建的不可控峰值。
在 5.7 中,我们默认将此执行器限制为最多 1000 个线程,我们认为这应该足以满足大多数用例。在大量繁忙会话的情况下,每个会话最终都可能使用大量线程,最终导致您的应用程序出现 OOM。您可以做几件事。最明显的事情是降低会话可以使用的最大线程限制,例如
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
connectionFactory.setMaxThreadPoolSize(10);
Connection conn = connectionFactory.createConnection();
conn.start();
另一方面,这会导致单个会话耗尽其最大线程数量的情况。在这种情况下,ThreadPoolExecutor
的默认行为是抛出异常,因此您会注意到它。此场景的解决方法是提供一个拒绝的任务处理程序,它将与调用线程同步执行,例如
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
connectionFactory.setRejectedTaskHandler(new ThreadPoolExecutor.CallerRunsPolicy());
Connection conn = connectionFactory.createConnection();
conn.start();
这将阻止 ThreadPoolExecutor
在达到其绑定时抛出异常。相反,它将在调用线程中执行拒绝的任务。
最后,您可以完全消除这些线程,可以通过将 alwaysSessionAsync
属性设置为 false 来实现
ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("tcp://127.0.0.1:61616");
connectionFactory.setAlwaysSessionAsync(false);
Connection conn = connectionFactory.createConnection();
conn.start();
但是您需要记住,这种方法会影响整个系统的性能。
所以就是这样。在您的应用程序难以处理由 JMS 会话创建的线程数量的不常见情况下,您可以使用其中一种显示的技术来处理它。与往常一样,没有适合所有情况的灵丹妙药,因此请衡量和调整您的系统。