Размер JMS-сообщения

В настоящее время я работаю над функцией ограничения пропускной способности (не спрашивайте меня, почему, это не мое решение) для приложения, которое использует JMS (а именно Spring framework JMS и Active MQ) для отправки сообщений с полезной нагрузкой между сервером и клиентами.

Я нашел множество методов регулирования для ограничения входящих сообщений JMS (но ни один из них не основан на фактической нагрузке на полосу пропускания), однако я не нашел никакого возможного способа ограничить поток исходящих сообщений. Поэтому я решил написать алгоритм дырявого ведра самостоятельно.

Есть ли способ получить размер сообщения JMS? Кроме реализации sizeof в Java (Как в Java лучше всего определить размер объекта?)


person Sorceror    schedule 17.08.2011    source источник
comment
Почему недостаточно ограничить поток входящих сообщений, что ActiveMQ позволяет вам делать с использованием производителя FlowControl и memoryLimits в пунктах назначения. Мне любопытно узнать, почему вы также хотите ограничить исходящие сообщения. Кроме того, не будет ли этот тип вещей лучше контролироваться с помощью какого-то контроллера доставки приложений, сидящего перед вашим брокером (при условии, что у вас даже есть такая возможность).   -  person whaley    schedule 18.08.2011
comment
Наш клиент хочет ограничить исходящую полосу пропускания от производителей (скажем, у клиента пропускная способность 100 Мбит, но он хочет использовать только 10 Мбит). Это сводит меня с ума. JMS предназначен для доставки сообщений как можно скорее, поэтому я не очень понимаю это требование. Но, к сожалению, это не мое решение.   -  person Sorceror    schedule 18.08.2011


Ответы (3)


Я не думаю, что у вас есть какая-либо серьезно лучшая альтернатива для определения размера сообщения JMS, чем измерение его сериализованного размера.

Но вы можете добавить некоторые оптимизации, если хотите. Существует несколько типов сообщений (например, MapMessage, ObjectMessage, TextMessage).

Размер текстового сообщения равен длине его текста. Размер сообщения карты равен общему размеру всех его полей. Поля являются примитивами или java.util.Date, поэтому измерить их не проблема. Сообщение объекта содержит сериализуемый объект, поэтому вы можете измерить его размер, записав в ByteOutputStream.

Я думаю, что реализация дырявого ведра с использованием JMS может быть упрощена, если вы используете скрытую функцию большинства провайдеров JMS для отправки отложенных сообщений. Вы можете измерить сообщение при его постановке в очередь и решить, когда вы хотите, чтобы подписчик получил его. Подробнее о том, как отправлять отложенные сообщения, читайте здесь: http://alexradzin.blogspot.com/2010/10/send-delayed-jms-messages.html

person AlexR    schedule 17.08.2011

Поскольку сообщения JMS сериализуются в процессе отправки, лучший способ получить размер сообщения — через ObjectOutputStream.

private int getMessageSizeInBytes(MessageWrapper message) throws IOException {
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    ObjectOutputStream oos = new ObjectOutputStream(baos);
    oos.writeObject(message);
    oos.close();
    return baos.size();
}
person Sorceror    schedule 16.01.2012

В дополнение к более раннему комментарию @AlexR, BytesMessage имеет метод getBodyLength()

http://download.oracle.com/javaee/1.4/api/javax/jms/BytesMessage.html#getBodyLength

и вы, вероятно, можете оценить типичный размер заголовка при передаче, захватив несколько объектов, созданных с помощью Session.createMessage(), то есть тип сообщения JMS без полезной нагрузки. Я думаю, у меня возникнет соблазн работать напрямую с полезной нагрузкой в ​​байте [], используя BytesMessage, и сжимать через ZipOutputStream, если пропускная способность критична. Кроме того, JMS позволяет подсказкам скрывать отметку времени и идентификатор сообщения, что может помочь уменьшить размер сообщения, например.

http://download.oracle.com/javaee/1.4/api/javax/jms/MessageProducer.html#setDisableMessageTimestamp%28boolean%29

хотя провайдеры не обязаны его поддерживать,

Если провайдер JMS принимает эту подсказку, эти сообщения должны иметь идентификатор сообщения, равный нулю; если провайдер игнорирует подсказку, для идентификатора сообщения должно быть установлено его обычное уникальное значение.

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

person strmqm    schedule 17.08.2011
comment
Пропускная способность не критична, наш клиент просто хочет управлять пропускной способностью. +1 за getBodyLength(), но я боюсь, что это сработает только для BytesMessage экземпляров, которых, я полагаю, у меня нет.. - person Sorceror; 18.08.2011