MQ - 队列上的数据压缩

3
问题:MQ7有一个最大100MB的JMS消息硬性限制。对于接近此限制的大型有效载荷(XML),是否可以在队列上进行压缩以缩短数据长度?
尝试使用MQ ZLIB压缩对一个7MB JMS字符串消息进行压缩,但在svr.def.conn通道上并没有使JMS消息的数据长度发生任何变化。我只设置了一个通道,并期望使用的通道会压缩进入队列的数据。
MQ服务器:7.5 客户端:JAVA 消息类型:字符串
2个回答

1
通道级压缩用于在通道两端传输数据时进行压缩,例如在JMS客户端和MQ SVRCONN通道之间。消息在通过网络传输时会被压缩,但在队列中等待时不会被压缩。

因此,为避免100MB的硬限制,实际数据压缩将无济于事。队列中的数据是否有压缩?我想我可以考虑发送一个zip文件。 - haju
@haju 没错,只有在从一个点传输到另一个点时才会进行压缩。IBM MQ没有任何队列级别的压缩。请参考最近的这个问题,在问题的评论中可以找到一些额外的想法:https://stackoverflow.com/questions/45063062/channel-compression-in-ibm-mq-classes-for-java - JoshMc

1
我建议压缩有效载荷并使用ByteMessage。消息属性可用于限定有效载荷类型,类似于HTTP的“Content-Encoding”、“Content-Type”。
String payload = ...; // the xml

Session session = ...;
BytesMessage bytesMessage = session.createBytesMessage();

bytesMessage.writeBytes(compressGZIP(payload, StandardCharsets.UTF_8));
bytesMessage.setStringProperty("Content-Encoding", "gzip");
bytesMessage.setStringProperty("Content-Type", "text/xml; charset=utf-8");

这是 compressGZIP 方法:

private byte[] compressGZIP(String string, Charset charset) throws IOException {
    ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
    try (GZIPOutputStream out = new GZIPOutputStream(byteArrayOutputStream)) {
        StringReader stringReader = new StringReader(string);
        // IOUtils from apache commons-io
        IOUtils.copy(stringReader, out, charset);
    }
    return byteArrayOutputStream.toByteArray();
}

消费者可以请求消息属性,根据“Content-Encoding”和“Content-Type”消息属性进行解压缩并重新创建基于xml的消息。
类似这样的东西。
public void onMessage(Message message) {
    BytesMessage bytesMessage = (BytesMessage) message;

    long bodyLength = bytesMessage.getBodyLength();
    byte[] rawPayload = new byte[(int) bodyLength];
    InputStream payloadInputStream = new ByteArrayInputStream(rawPayload);

    String contentEncoding = bytesMessage.getStringProperty("Content-Encoding");
    if("gzip".equals(contentEncoding)) {
        payloadInputStream = new GZIPInputStream(payloadInputStream);
    }

    String contentType = bytesMessage.getStringProperty("Content-Type");
    MimeType mimeType = new MimeType(contentType); // from javax.activation

    if("text".equals(mimeType.getPrimaryType())) {
        if("xml".equals(mimeType.getSubType())) {
            Charset charset;

            String charsetString = mimeType.getParameter("charset");
            if(charsetString != null) {
                charset = Charset.forName(charsetString);
            } else {
                charset = StandardCharsets.UTF_8; // default
            }

            Reader reader = new InputStreamReader(payloadInputStream, charset);

            String xml = IOUtils.toString(reader);
            IOUtils.closeQuietly(reader);
        }
    }
}

这种解决方案的优点是您可以继续使用标准的JMS API,而不是使用特定于提供程序的配置。
缺点是发送方和接收方必须实现内容类型处理。
因此,您必须在可移植性和实现工作量之间做出决策。

1
Base64更好。可以很好地压缩它。 - haju

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接