我们使用ActiveMQ作为消息传递层–发送大量需要低延迟的消息。 通常它可以正常工作,但是在某些情况下我们遇到了性能问题。 在花了太多时间测试我们的基础架构之后,我想我已经学到了有关ActiveMQ的一些有趣的东西:它可能真的很慢。
尽管一般来说,消息通过ActiveMQ传输不会出现问题,但是我们注意到,当我们收到大量消息时,就会开始看到延迟。 好像我们正在达到某个消息速率限制–当我们超过该消息速率限制时,消息将被延迟,仅在该限制处传递。 从ActiveMQ贴上消息的时间戳起,我们可以看到代理正在快速接受消息,但是发送给使用者的时间有所延迟。
我设置了一个测试工具来复制问题-这很容易。 但是,我在测试系统中测得的吞吐量似乎很低:每秒2500条消息。 对于一个非常简单的消费者而言,基本上什么也不做,因此没有理由将吞吐量如此之低。 为了进行比较,在完全相同的设置中使用定制的消息传递层,我们达到了每秒15,000条消息。 第二个难题是在生产中,我们看到的消息速率仅为250消息/秒。 为什么测试系统比生产系统快10倍?
我开始尝试消除可能性:
- ActiveMQ上的并发负载没有区别
- 更改生产者流量控制设置没有影响
- 更改使用者的预取限制只会使行为变得更糟(我们将数据写入非持久性主题,因此默认的预取限制很高)
- 似乎没有组件受到带宽或CPU限制
作为实验,我尝试将使用者与代理人和生产者移动到同一台服务器上:消息吞吐量增加了一倍。 将使用者移动到具有更高ping时间的服务器上:消息吞吐量骤降。
这导致了一种洞察力:ActiveMQ代理的行为恰好好像“一次”发送给消费者的数据量受到限制。 我特别意识到,网络上未确认的数据量似乎受到限制。 如果连线较长,则数据到达使用者的时间更长,而确认返回的时间也更长:因此,代理每秒发送较少的数据。
这种行为突出了我们的第一个错误。 我们使用Spring Integration处理用户端的消息路由,在一年前对Spring进行了升级,我们在该版本中获得的更改之一是对消息驱动通道适配器确认JMS消息的方式进行了更改。 以前,我们的消息是自动确认的,但是现在确认模式是“事务处理”的。 这意味着我们必须在将确认发送给代理之前完成整个消息处理链。
这就解释了为什么生产系统(对消息有用的工作)具有比测试系统低得多的数据速率。 不仅是消息必须经过1毫秒的ping时间,消费者还没有发送完确认消息,直到消费者完成了对消息的处理,这可能还要花费几毫秒的时间。
但是更糟糕的是,交易确认似乎完全阻止了用户预取数据! 我们通过事务确认看到的吞吐量是一次在线上一个未确认的消息。 如果我们将消费者移到更远的地方,我们的吞吐量将直线下降。 即,代理在收到之前的确认之前不会发送新消息。 与其代替消费者从经纪人那里预取数百条消息并依次处理它们,而是经纪人耐心地一次发送一条消息! 难怪我们的表现糟透了。
通过spring集成配置更改可以轻松解决此问题。 在测试系统中,我们的消息吞吐量从2500消息/秒增加到10,000消息/秒。 不错的进步。
但是我很好奇,我们仍然会看到经纪人的行为,好像网上未确认数据的数量受到限制吗? 因此,我将使用者转移到相距较远的服务器上进行测试。 结果? 是! 代理仍会限制网络上未确认的数据量。 即使自动确认了消息,对于代理将发送而没有看到确认的数据量也有一个硬性上限。
帽子的大小呢? 约64KB。 是的,在2018年,我的消息传递层一次只能传输64KB的数据。 当经纪人和消费者超级亲密时,这很好。 但是,将消费者与代理之间的ping时间增加到10ms,我们的消息速率将下降到5,000消息/秒。 在100毫秒的往返行程中,我们的消息速率为500消息/秒。
这种行为感觉就像应该控制预取限制:但是,我们看到的消息(不超过60条1kB消息)比预取限制所暗示的要少得多。 到目前为止,我还没有找到关于“消费者窗口大小”是否存在的任何确认。 也没有任何特别修改行为的方法。 使用方上TCP套接字缓冲区大小的增加将传输中的数据量增加到大约80KB,但没有增加。
我很困惑,很多人使用ActiveMQ,而且肯定有人会注意到像这样的数据上限吗? 但是,也许大多数人使用ActiveMQ的消费者和经纪人之间的ping时间非常短,根本就不会注意到它?
但是,人们必须在全球分布式部署中使用ActiveMQ –为什么没人能看到这一点?
翻译自: https://www.javacodegeeks.com/2018/09/activemq-performance-testing.html