У меня есть проект по передаче файла с помощью 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();
}
}