1

我们正在从 IBM MQ 迁移到 Amazon MQ,至少我们愿意这样做。问题是,与 IBM MQ 相比,使用 JMS 生产者将大消息放入队列时,Amazon MQ 的性能较差。

对于 IBM MQ,所有消息都是持久的,系统是高可用的,而 Amazon MQ 是多可用区。

如果我们将这种大小的 XML 文件放入 IBM MQ(2 cpu 和 8GB RAM HA 实例),我们将获得以下性能:

256 KB = 15ms
4,6 MB = 125ms
9,3 MB = 141ms 
18,7 MB = 218ms
37,4 MB = 628ms
74,8 MB = 1463ms

如果我们将相同的文件放在 Amazon MQ(mq.m5.2xlarge = 8 CPU 和 32 GB RAM)或 ActiveMQ 上,我们将获得以下性能:

256 KB = 967ms
4,6 MB = 1024ms
9,3 MB = 1828ms 
18,7 MB = 3550ms
37,4 MB = 8900ms
74,8 MB = 14405ms

我们还看到,IBM MQ 向队列发送消息和从队列获取消息的响应时间相同,而 Amazon MQ 在获取消息方面非常快(例如只需要 1 毫秒),但在发送时非常慢.

在 Amazon MQ 上,我们使用 OpenWire 协议。我们以 Terraform 样式使用此配置:

resource "aws_mq_broker" "default" {
  broker_name                = "bernardamazonmqtest"
  deployment_mode            = "ACTIVE_STANDBY_MULTI_AZ"
  engine_type                = "ActiveMQ
  engine_version             =  "5.15.10"
  host_instance_type         =  "mq.m5.2xlarge"
  auto_minor_version_upgrade =  "false"
  apply_immediately          =  "false"
  publicly_accessible        =  "false"
  security_groups            = [aws_security_group.pittensbSG-allow-mq-external.id]
  subnet_ids                 = [aws_subnet.pittensbSN-public-1.id, aws_subnet.pittensbSN-public-3.id]

  logs {
    general = "true"
    audit   = "true"
  }

我们通过 POM (Maven) 将 Java 8 与 JMS ActiveMQ 库一起使用:

<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-client</artifactId>
    <version>5.15.8</version>
</dependency>
<dependency>
    <groupId>org.apache.activemq</groupId>
    <artifactId>activemq-pool</artifactId>
    <version>5.15.8</version>
</dependency>

在 JMS 中,我们有以下 Java 代码:

private ActiveMQConnectionFactory mqConnectionFactory;
private PooledConnectionFactory mqPooledConnectionFactory;
private Connection connection;
private Session session;
private MessageProducer producer;
private TextMessage textMessage;
private Queue queue;

this.mqConnectionFactory = new ActiveMQConnectionFactory();
this.mqPooledConnectionFactory = new PooledConnectionFactory();
this.mqPooledConnectionFactory.setConnectionFactory(this.mqConnectionFactory);

this.mqConnectionFactory.setBrokerURL("ssl://tag-1.mq.eu-west-1.amazonaws.com:61617");

this.mqPooledConnectionFactory.setMaxConnections(10);

this.connection = mqPooledConnectionFactory.createConnection());
this.connection.start();

this.session = this.connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
this.session.createQueue("ExampleQueue");

this.producer = this.session.createProducer(this.queue);
long startTimeSchrijf = 0;
startTimeWrite= System.currentTimeMillis();
producer.send("XMLFile.xml");  // here we send the files
logger.debug("EXPORTTIJD_PUT - Put to queue takes: " + (System.currentTimeMillis() - startTimeWrite));

// close session, producer and connection after 10 cycles

我们还作为单实例 AmazonMQ 运行了性能测试。但同样的结果。我们还使用 mq.m5.4xlarge(16 cpu,96 GB RAM)引擎运行了性能测试,但仍然没有改善糟糕的性能。

性能测试配置:我们首先将上述消息(XML文件)一个一个地推送到队列中。我们这样做了 5 次。5 次后,我们从队列中读取这些消息(XML 文件)。我们称之为 1 个周期。

我们一个接一个地运行 10 个周期,因此我们总共将 300 个文件推送到队列中,并且从队列中获取了 300 个文件。

我们并行运行 3 项测试:一项来自 AWS 地区伦敦,一项来自 AWS 地区法兰克福,位于不同的 VPC 中,1 项来自法兰克福,位于与 Amazon MQ 代理相同的 VPC 中且位于同一子网中。所有客户端都在 EC2 实例上运行:m4.xlarge。

如果我们仅使用一个 VPC 运行测试,例如仅与 AmazonMQ 代理位于同一子网中的本地 VPC,则性能会提高,我们会得到以下结果:

256 KB = 72ms
4,6 MB = 381ms
9,3 MB = 980ms 
18,7 MB = 2117ms
37,4 MB = 3985ms
74,8 MB = 7781ms

客户端和服务器在同一个子网中,所以我们与防火墙等无关。

也许有人可以告诉我哪里出了问题,为什么我们的 Amazon MQ 或 ActiveMQ 性能如此糟糕?

额外信息:响应时间在 JMS Java 应用程序中测量,Java 开始时间在 producer.send('XML') 之前,结束时间在 producer.send('XML') 之后。差异是记录的时间。时间是超过 300 次呼叫的平均时间。
IBM MQ 服务器位于我们的数据中心,客户端应用程序在同一数据中心的服务器上运行。

额外信息测试:jms 应用程序开始创建 connectionFactory 队列会话。然后它将文件逐个上传到 MQ 1。这是一个循环,然后它在 for lus 中运行此循环 10 次,而不打开或关闭会话队列或连接工厂。然后从队列中读取所有 60 条消息并写入本地驱动器上的文件。然后它关闭连接工厂和会话以及生产者/消费者。这是一批。然后我们运行 5 个批次。因此在批次之间重新创建连接工厂、队列、会话。

作为对 Sam 的回应:当我也像 Sam 一样使用相同大小的文件执行测试时,我接近相同的响应时间,我将持久性模式也设置为 () 之间的 false 值:

500 KB = 30ms (6ms)
1 MB = 50ms (13ms)
2 MB = 100ms (24ms)

我删除了连接池并设置了 concurrentStoreAndDispatchQueues="false" 我使用的系统是代理:mq.m5.2xlarge 和客户端:m4.xlarge。

但如果我用更大的文件进行测试,这是响应时间:

256 KB = 72ms
4,6 MB = 381ms
9,3 MB = 980ms 
18,7 MB = 2117ms
37,4 MB = 3985ms
74,8 MB = 7781ms

我有一个非常简单的要求。我有一个系统,它将消息放在队列中,并且消息是由另一个系统从队列中获取的,有时同时有时不是,有时系统上有 20 或 30 条消息在它们被卸载之前。这就是为什么我需要一个队列并且消息必须是持久的并且它必须是 Java JMS 实现。

我认为 Amazon MQ 可能是小文件的解决方案,但对于大文件却不是。我认为我们必须在这种情况下使用 IBM MQ,它具有更好的性能。但有一件重要的事情:我只在我们的 LAN 中测试了 IBM MQ。我们尝试在 Amazon 上测试 IBM MQ,但尚未成功。

4

2 回答 2

0

我试图重现您正在测试的场景。当我在与具有活动和备用实例的 mq.m5.4xlarge 代理的 AmazonMQ 代理相同的 VPC 中运行 JMS 客户端时,我看到以下往返延迟 - 测量从生产者发送消息的时刻到消费者发送消息的时刻收到消息。

2MB - 50ms
1MB - 31ms
500KB - 15ms

我的代码刚刚创建了一个连接和一个会话。我没有使用 PooledConnectionFactory (事实上说明了这一点,而不是说/怀疑这是原因)。此外,最好将代码精简到最低限度,以便在进行性能测试时建立基线并消除噪音。这样,当您引入其他代码时,您可以轻松查看新代码是否引入了性能问题。我使用了默认的代理配置。

在 ActiveMQ 中,有 Fast Producer 和 Fast Consumer 的概念,也就是说,如果消费者能够以与 Producer 相同的速率处理消息,则 broker 通过内存将消息从生产者传递给消费者,然后将消息写入磁盘. 这是默认行为,由名为concurrentStoreAndDispatch的代理配置设置控制,该设置为true(默认)

如果消费者无法跟上生产者的步伐,从而成为“慢”消费者,并且将 concurrentStoreAndDispatch 标志设置为 true,那么您的性能就会受到影响。

ActiveMQ 提供咨询主题,您可以订阅这些主题以检测慢速消费者。如果实际上您检测到消费者比生产者慢,最好将 concurrentStoreAndDispatch 标志设置为 false 以获得更好的性能。

于 2020-04-14T23:31:37.443 回答
0

我没有得到任何回应。我认为这是因为这个性能问题没有解决方案。Amazon MQ 是一种云服务,也许这就是性能如此糟糕的原因。IBM MQ 是一种不同的体系结构,它是在内部部署的。

我必须进一步调查 ActiveMQ 的性能,然后才能说出这个问题的确切原因。

于 2020-03-30T19:08:20.433 回答