用于传输大量文件的 IBM MQ 调优

Posted

技术标签:

【中文标题】用于传输大量文件的 IBM MQ 调优【英文标题】:IBM MQ tuning for tranfer a large number of file 【发布时间】:2020-08-23 20:05:20 【问题描述】:

我有一个使用 IBM MQ 传输文件的项目。有10000个客户端和一个数据中心。最大的文件大小几乎是 8MB。 MQ 集群包含三个 MQ 管理器,它们位于不同的 Windows 服务器上。每个 MQ 管理器有 5 个客户端通道和 5 个数据中心通道。有两种情况可供测试。在每种情况下,客户端被平均分配给 MQ 管理器。在这些情况下,不要丢失任何文件是最重要的。

Case 1:
Every client send 50 files to data center at the same time. The files size are between 150KB to 5MB. 
In this case, the sum of file size one client send is almost 80MB.

Case 2 :
Data center send the 10 identical files to every client at the same time. In this case, I create a topic named `myTopic` and 10000 clients subscribe this topic. Data center send 10 identical files to the topic.

MQ Manger 的负载很重。我已经在 IBM MQ 中设置了一些属性:

Queue Manager:
    Max handles: 100000
    Maximum message length: 100MB
    Max channels: 10000
    Max channels: 10000

有没有什么属性可以提高性能?

5/11 更新:

首先,我修改了上面案例2的情况。我有一个具有 4 核 CPU 和 32G RAM 的数据中心服务器。我用4个客户端服务器模拟10000个客户端,每个客户端服务器有4核CPU和16G RAM。

在案例 1 中,1000 个客户端向数据中心发送文件大约需要 37 分钟。数据中心从 2000 个客户端接收文件时,数据中心服务器内存不足。我发现有 20G 内存用于缓冲区/缓存。这是我用来接收文件的java代码:

try 
    String filePath = ConfigReader.getInstance().getConfig("filePath");

    MQMessage mqMsg = new MQMessage();
    mqMsg.messageId = CMQC.MQMI_NONE;
    mqMsg.correlationId = CMQC.MQCI_NONE;
    mqMsg.groupId = CMQC.MQGI_NONE;

    int flag = 1;

    while (true) 
        try 
            MQQueueManager queueManager = new MQQueueManager("QMGR1");
            int option = CMQC.MQTOPIC_OPEN_AS_SUBSCRIPTION | CMQC.MQSO_DURABLE;
            MQTopic subscriber = queueManager.accessTopic("", "myTopic", option, null, "datacenter");
            subscriber.get(mqMsg);

            if (mqMsg.getDataLength() != 0) 
                String fileName = filePath + "_file" + flag + ".txt";

                byte[] b = new byte[mqMsg.getDataLength()];
                mqMsg.readFully(b);

                System.out.println("Receive " + fileName + ", complete time: " + System.currentTimeMillis());
                Path path = Paths.get(fileName);
                System.out.println("Write " + fileName + ", start time: " + System.currentTimeMillis());
                Files.write(path, b);
                System.out.println("Write " + fileName + ", complete time: " + System.currentTimeMillis());
                flag++;
            
         catch (MQException e) 
            // e.printStackTrace();
            if (e.reasonCode != 2033) 
                e.printStackTrace();
            
         finally 
            mqMsg.clearMessage();
            mqMsg.messageId = CMQC.MQMI_NONE;
            mqMsg.correlationId = CMQC.MQCI_NONE;
            mqMsg.groupId = CMQC.MQGI_NONE;
        
    
 catch (Exception e) 
    // TODO Auto-generated catch block
    e.printStackTrace();

我使用字节数组读取消息并将其写入磁盘。是不是字节数组不释放内存,占用20G内存?

在情况 2 中,我发现如果我向 myTopic 发送一个 5MB 的文件,在 MQ manager01 上拥有 1000 个订阅者,MQ manager01 需要花费大量时间与集群成员同步。 MQ 服务器上的磁盘非常繁忙。还有一个问题:有时我只需要 7 秒来发送一个 5MB 的文件,有时需要 90 秒。这是我发送文件的 java 代码:

try 
    MQQueueManager queueManager = new MQQueueManager("QMGR1");
    MQTopic publisher = queueManager.accessTopic("myTopic", "", CMQC.MQTOPIC_OPEN_AS_PUBLICATION,
            CMQC.MQOO_OUTPUT);
    System.out.println("---- start publish , time: " + System.currentTimeMillis() + " ----");
    publisher.put(InMemoryDataProvider.getInstance().getMessage("my5MBFile"));
    System.out.println("---- end publish , time: " + System.currentTimeMillis() + " ----");
    publish.getPublisher().close();
 catch (MQException e) 
    System.out.println("threadNum: " + publish.getThreadNo() + " publish error");
    if (e.reasonCode != 2033) 
        e.printStackTrace();
    

【问题讨论】:

如果与客户端的网络连接是限制因素,则通道上的压缩会有所帮助。这只是一个猜测,因为您还没有描述现在您正在尝试改进的性能是什么,或者当前的瓶颈在哪里。 同意@JoshMc 压缩——它使用的 CPU 很少成为消息传递的瓶颈。多少个CPU?服务器的磁盘性能是多少? NVME 存储将为您带来巨大的提升,而 RAID SSD 紧随其后。 你应该在这个网站上试试,这就是他们所做的一切:mqseries.net 您正在执行一个没有延迟的 get 循环,据我所知,每次都打开一个与队列管理器的新连接,我确信这应该在某个时候失败,你不接收和 MQ 异常?最好在循环之前创建与队列管理器的连接并订阅主题 1 次,在循环中您只需执行获取并添加等待间隔,等待是 MQ 之前等待队列上的消息的时间它返回 2033,只要它出现在队列中,您仍然会收到该消息。 能否显示主题对象和持久模型队列? 【参考方案1】:

几件事。

MQ 具有为您传输文件的 FTE。我认为它使用非持久消息来实现,因此可以避免磁盘开销。

您可以尝试检查 .ini 文件中的参数,例如 ClntRcvBuffSize=0 见here。 0 表示使用操作系统值。

TCP 用于以短数据包(64KB 块)发送一些数据,然后等待数据包被确认,然后再发送更多数据。如果连接可靠,那么您可以通过发送更大的逻辑数据包来获得更高的吞吐量,这种技术称为动态正确调整大小。见here

当连接长期存在并发送大量数据时,它的效果最佳。例如,前几个块可能是 64KB,然后将其稍微增加到 128KB,如果需要,最终增加到 100MB(或更多)。

你需要设置两端。

根据平台,您可以使用 Netstat 替换 ss 命令来显示各种窗口大小。

为您的 QM 到 QM 通道指定一个大的 batchsz 和 batchlim - 虽然随着数据更快地到达远程端,这可能会使您的磁盘 IO 变得更糟。

【讨论】:

以上是关于用于传输大量文件的 IBM MQ 调优的主要内容,如果未能解决你的问题,请参考以下文章

WEB性能调优:gzip 与 chunked

软件-MQ-MQ:IBM MQ

IBM的MQ和Active MQ相比都有哪些优点和不足?

Webapi传输大量大型文件[重复]

来自 IBM MQ 的 Spark 流数据

IBM websphere MQ远程队列的简单配置