首页 > 解决方案 > 多线程中的 MQ 与 REST 性能

问题描述

目前我有一个每秒处理数千个请求的消息传递引擎,性能很差,因为当前的实现正在使用一个阻塞操作的 REST 服务,所以它最终耗尽了线程池中的线程,因为使用了一个 REST服务在 HTTP 之上运行我的理解是,我无法触发“即发即弃”请求,至少我需要等待 HTTP 响应,即使使用了 Future 这将在其中运行一个不同的线程,所以即使主线程没有被阻塞,它最终还是会饿死线程池,所以我的问题是,如果我有这么高的并发数,将它发送到 MQ 不是更好吗?这样,这将不再是阻塞操作,对吗?该应用程序当前在 Akka 框架上运行。

标签: javamultithreadingperformancerestmq

解决方案


所以初始数据如下:

  • 您的程序每秒向 REST 服务发出数千个请求,
  • POST 请求耗时超过 1 秒,
  • 它最终耗尽了线程池中的线程。

您应该检查的第一件事:REST 服务能够承受多少并发请求?会不会每秒处理不了上千个请求,单次请求的大时序是服务超载的结果?然后你必须设置一个机制来限制你的请求速率。实际上,设置这样的限制在任何情况下都是一个好主意。

其次,您应该决定是否可以通过同步或异步 I/O 实现这样的访问速率。同步 I/O 更简单、更快,但需要更多的线程消耗内存。粗略估计如下:

  • 少于 100 个同时请求:使用同步
  • 超过 10000 个并发请求:使用异步
  • 介于两者之间:无论哪种方式

如果您决定使用同步 I/O,那么设置请求速率限制的最简单和自然的方法是使用信号量:想要发出下一个请求的线程获取信号量对象,并在收到回复后释放它。保持线程池中的线程数等于请求限制。

如果您决定使用异步 I/O,则没有通用机制来设置这样的限制,因为异步信号量通常对开发人员不可用。如果您的异步 I/O 库具有响应式接口,请使用它(异步信号量是背压机制的一部分)。如果没有,您可以使用以下组件创建这样的机制:

  • 异步请求的阻塞队列
  • 限制信号量
  • 一个线程,它在一个循环中执行以下操作:获取信号量,从队列中获取下一个请求,然后发出它。当请求完成时(无论成功与否),信号量由请求的回调释放。

这种机制对所有异步请求使用单线程,因此消耗的内存不多,并且运行速度足够快。但是,如果您需要它更快地工作,只需增加线程数。


推荐阅读