【问题标题】:MQ - Data Compression on queueMQ - 队列上的数据压缩
【发布时间】:2021-04-27 16:22:16
【问题描述】:

问题:MQ7 有一个最大 100MB jms 消息的硬性限制。对于接近的大型有效载荷( xml ),是否可以在队列上对其进行压缩以缩短数据长度?

我尝试在 svr.def.conn 通道上使用 MQ ZLIB 压缩来压缩 7MB jms 字符串消息,它对 jms 消息的数据长度没有任何影响。我只设置了一个通道,并期望使用的通道会压缩进入队列的数据。

MQ 服务器:7.5 客户:JAVA 消息类型:字符串

【问题讨论】:

    标签: compression jms ibm-mq


    【解决方案1】:

    通道级压缩用于压缩通道两端之间传输的数据,在您的情况下,在 JMS 客户端和 MQ SVRCONN 通道之间。消息本身将在通过网络时被压缩,但在排队时不会被压缩。

    【讨论】:

    • 所以它不会对实际的数据压缩做任何事情来避免 100MB 的硬限制。队列中的数据是否有任何压缩?我想我可以看看发送一个 zip 文件
    • @haju 这是正确的,只有当它通过网络从点到点传输时。 IBM MQ 没有任何队列级压缩。有关问题的 cmets 中的一些其他想法,请参阅这个最近的问题:stackoverflow.com/questions/45063062/…
    【解决方案2】:

    我建议压缩有效负载并使用ByteMessage。消息属性可用于限定有效负载类型,类似于 HTTP,例如“内容编码”、“内容类型”

    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,而不是使用提供程序特定的配置。

    缺点是发送方和接收方必须实现内容类型处理。

    因此,您必须在可移植性和实施工作之间做出决定。

    【讨论】:

    • Base64 更好。很好地压缩它。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-12-15
    • 1970-01-01
    • 2013-04-09
    • 1970-01-01
    相关资源
    最近更新 更多