Настройка IBM MQ для передачи большого количества файлов - PullRequest
0 голосов
/ 08 мая 2020

У меня есть проект по передаче файла с помощью IBM MQ. Есть 10000 клиентов и один дата-центр. Самый большой размер файла - почти 8 МБ. Кластер MQ содержит три менеджера MQ, которые находятся на разных серверах Windows. Каждый менеджер MQ имеет 5 каналов для клиента и 5 каналов для центра обработки данных. Есть два случая для тестирования. В каждом случае клиенты равномерно распределяются по MQ Manager. В таких случаях важнее всего не потерять файлы.

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 большая нагрузка. Я уже установил какой-то атрибут в IBM MQ:

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

Есть ли какой-нибудь атрибут, который может повысить производительность?

5/11 update:

Во-первых, я изменил ситуация случая 2 выше. У меня есть сервер центра обработки данных с 4-ядерным процессором и 32 ГБ ОЗУ. Я использую 4 клиентских сервера для имитации 10000 клиентов, и каждый клиентский сервер имеет 4 ядра ЦП и 16 ГБ ОЗУ.

В случае 1 требуется около 37 минут, когда 1000 клиентов отправляют файлы в центр обработки данных. Когда дата-центр принимает файлы от 2000 клиентов, на сервере центра обработки данных не хватает памяти. Я обнаружил, что для буфера / кеша используется 20 ГБ памяти. Вот мой код 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();
}

Я использую массив байтов для чтения сообщения и записи его на диск. Возможно ли, что массив байтов не освобождает память и занимает 20 ГБ памяти?

В случае 2 я обнаружил, что отправлю файл размером 5 МБ на myTopic, у которого 1000 подписчиков на MQ manager01, MQ manager01 требуется много времени для синхронизации c с членом кластера. Диски на серверах MQ очень заняты. Есть еще одна проблема: иногда мне дается всего 7 секунд на отправку файла размером 5 МБ, иногда это занимает 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();
    }
}

1 Ответ

0 голосов
/ 13 мая 2020

Пара вещей.

MQ имеет FTE, который передает файлы за вас. Я думаю, что он использует непостоянные сообщения, поэтому вы избегаете накладных расходов на диск.

Вы можете попробовать проверить свои .ini файлы на такие параметры, как ClntRcvBuffSize = 0, см. здесь . 0 говорит, что использовать значения операционной системы.

TCP используется для отправки некоторых данных короткими пакетами (фрагмент 64 КБ), затем подождите, пока пакеты не будут подтверждены, и отправьте еще. Если соединение является надежным, вы получаете более высокую пропускную способность, отправляя более крупные логические пакеты, метод, известный как Dynami c Right Sizing. См. здесь

он работает лучше всего, когда соединение является долгим и отправляет много данных. Например, первые несколько фрагментов могут иметь размер 64 КБ, затем увеличьте его немного до фрагментов 128 КБ, в конечном итоге до 100 МБ (или более), если необходимо.

Вам необходимо установить оба конца.

В зависимости от на платформе вы можете использовать команду Netstat replacement ss для отображения окон различных размеров.

Для ваших каналов QM to QM укажите большие пакеты z и batchlim - хотя это может ухудшить ввод-вывод вашего диска, поскольку данные попадают в удаленный конец быстрее.

...