Как избежать слишком большого количества экземпляров канала IBM MQ?
Я создал небольшую Java-программу, которая использует клиентские классы MQ для связи с сервером Websphere MQ и очередью на нем. Я хочу запрашивать размер, глубину ошибки определенной очереди через равные промежутки времени, например каждые 10 секунд.
Что я делаю, схематично:
qm = new MQQManager()
q = qm.accessQueue()
depth = q.getCurrentDepth()
- (сделать что-то с
depth
) q.close()
qm.close()
Это работает как шарм!
Из-за лени я написал свой код, чтобы каждый раз проходить все 6 шагов описанной выше последовательности. В итоге я повторял этот цикл каждые 10 секунд. Примерно через полчаса люди, которые следили за сервером, сказали мне, что на нем открыто 153 экземпляра. Понятно, просто делаю close()
в очереди и QM не достаточно, чтобы убирать за собой.
Я собираюсь сделать очевидное исправление и удержать QM и очередь на всю жизнь программы. Но может кто-нибудь сказать мне, почему мой предыдущий подход заключается в утечке ресурсов, и что я мог бы сделать с этим, если я выбрал этот путь?
ОБНОВЛЕНИЕ (2017-01-25)
Сроки и принятие
Роджер предоставил красивый код и несколько полезных объяснений на темы производительности и незафиксированных сообщений. Это круто, но ответа Юджина было точно (и минимально) достаточно, чтобы решить мою проблему, и он был немного быстрее. Мое маленькое приложение теперь делает именно то, что я хочу после того, как я просто изменил close()
в disconnect()
по совету Евгения. Теперь я немного волнуюсь о том, кто должен получить галочку. Мои извинения вам обоим!
Я получил именно то, что хотел, и думаю, что я закончил с этим вопросом, но я должен добавить, что я ценю вдумчивый ответ Роджера за полезную информацию, которую он предоставляет любому возможному будущему другому читателю этого вопроса. Надеюсь, другие люди будут слушать его, а не следовать моему примеру.
Спектакль
Если честно, мне наплевать на производительность. Сервер гораздо толще, чем нужно для того, что он в данный момент делает, и мой клиент для мониторинга (тема этого вопроса) работает на машине для разработки, которая обычно пуста. Я надеюсь, что это выполнит свою задачу в течение дня или двух, тогда я выброшу это. В то же время, если одно соединение каждые 10 секунд вызывает проблемы с производительностью, они должны балансировать нагрузку на Raspberry Pi или что-то еще.
Незафиксированные сообщения
Я думаю, что это тоже не проблема. Отправляющее приложение ставит в очередь небольшими партиями около 1-5 сообщений в течение нескольких миллисекунд и немедленно фиксирует. Принимающее приложение (клиент, которого я написал, и у него вполне могут быть проблемы) постоянно прослушивает очередь, получает и подтверждает (подтверждает) каждое сообщение в отдельности. Поэтому я уверен, что никогда не будет более 1, возможно, 5 неподтвержденных сообщений. Это число незначительно по сравнению с параметрами...
моя настоящая проблема,
что включает в себя несколько сотен сообщений с задержкой обработки от 5 до 20 минут примерно в одно и то же время каждое утро. Я подозреваю, что мой клиент-получатель зависает из-за "зависания" сетевой операции ввода-вывода с чем-то отличным от MQS. Один из шагов, который я хочу предпринять для изучения этого, состоит в том, чтобы продемонстрировать, что действительно существует очередь ожидающих сообщений в MQS, и она не принимается. Я хотел бы видеть, когда эта очередь начинает накапливаться, сколько времени она там находится и как быстро она спадает, когда мой клиент снова просыпается.
Эта связь видит от 2000 до 10000 сообщений в день с пиками, соответствующими пакетным процессам во второй половине дня и вечером, но задержки происходят только утром, часто с довольно небольшими объемами, которые на самом деле проходят. Я хотел бы видеть журнал размеров очереди, чтобы получить лучшее представление о том, что происходит. В качестве следующего шага мне, вероятно, понадобится больше инструментов в моем принимающем клиенте.
Среда
На сервере стоит WSMQ 6, поэтому мой клиент использует блокировку и ожидание очереди, а не аккуратный асинхронный процесс уведомления, который я бы предпочел использовать. Мой принимающий клиент - это отдельное приложение C, работающее под RHEL на виртуальной машине.
2 ответа
Вот Это Да! Не очень эффективный код. Соединение является FAR самым дорогим вызовом MQ API. Кроме того, получение глубины очереди не имеет смысла. Это дает вам ВСЕ непринятые и зафиксированные сообщения в очереди. то есть глубина очереди может сказать, что в очереди 5 сообщений, но ваша программа может получить только 3!! Вы могли бы сказать, что MQ не работает, но на самом деле 2 сообщения не переданы, следовательно, недоступны для потребителя.
Если вы действительно хотите получать и регистрировать информацию каждые 10 секунд, оставайтесь на связи.
Вот лучший способ сделать это:
boolean working = true;
int openOptions = CMQC.MQOO_INQUIRE + CMQC.MQOO_FAIL_IF_QUIESCING;
int depth = 0;
MQQueueManager qm = null;
MQQueue q = null;
try
{
qm = new MQQueueManager("MQA1");
while (working)
{
try
{
q = qm.accessQueue("TEST.Q1", openOptions);
depth = q.getCurrentDepth();
// (do something with depth)
}
catch (MQException e)
{
System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
System.out.println(e.getLocalizedMessage() );
working = false;
}
finally
{
if (q != null)
{
q.close();
q = null;
}
}
try
{
if (working)
Thread.sleep(10*1000); // time in milliseconds
}
catch (InterruptedException ie) {}
}
}
catch (MQException e)
{
System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
System.out.println(e.getLocalizedMessage() );
}
finally
{
try
{
if (q != null)
q.close();
}
catch (MQException e)
{
System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
System.out.println(e.getLocalizedMessage() );
}
try
{
if (qm != null)
qm.disconnect();
}
catch (MQException e)
{
System.out.println("CC = " + e.completionCode + " : RC=" + e.reasonCode);
System.out.println(e.getLocalizedMessage() );
}
}
Я думаю, что вы действительно должны использовать Disnect в блоке finally вместо close.