【问题标题】:Implement compression while sending hashMap over the network on Weblogic 11g server在 Weblogic 11g 服务器上通过网络发送 hashMap 时实现压缩
【发布时间】:2016-11-29 07:41:55
【问题描述】:

我有一个 hashMap 需要通过网络从服务器传输到客户端。现在,当大小增加超过套接字缓冲区提供的某个限制时,将引发以下异常。

原因:weblogic.socket.MaxMessageSizeExceededException:传入消息的大小:“3002880”字节超过了为协议配置的最大值:“3000000”字节:“t3”

在谷歌搜索时,我发现应该增加套接字大小,但这不是必需的,因为这不是一个很好的解决方案。

然后我尝试在使用“DeflaterOutputStream/InflaterInputStream”发送之前压缩 HashMap。但这里的挑战是“ObjectOutputStream”对象是由 weblogic 类创建的,并且应该在尝试创建 ObjectOutputStream 以使压缩工作时嵌入 deflater/Inflater 流。

有什么办法可以做到这一点吗?

还可以有一些方法来启用 weblogic 使用的 t3 协议的压缩以自动使用压缩。我已经对 t3 协议是否可能进行了一些研究,但似乎 t3 协议不支持这一点。但是我不确定一些新版本的 weblogic 是否支持这个。

我还考虑将 HashMap 分解为“套接字缓冲区大小”的块,但它需要更改现有设计,目前不推荐。

请分享您对此的看法。

【问题讨论】:

  • 3000000 对你来说是一个神圣的限制吗?如果没有并且可以修改,您可以尝试以下操作,System.setProperty("weblogic.MaxMessageSize", "BiggerValueAsString")。更多信息blogs.oracle.com/LuzMestre/entry/how_to_fix_weblogic_socket
  • @patrik 实际上我们的团队不想寻求解决方案,因为只要我们有更多数据,就需要尽快设置大小

标签: java serialization hashmap compression weblogic


【解决方案1】:

如果HashMap 将来可能包含更多数据,压缩它也只是一个临时解决方案。永久解决的方法是,如果地图中的项目太多,则将请求拆分为多个请求。

【讨论】:

  • 是的,你是对的,但是通过压缩我可以压缩到 90%。因此,最多 100 MB 的数据可以通过缓冲区大小为 10 Mb 的 s 套接字发送,而无需为套接字缓冲区申请更多内存。
【解决方案2】:

您可以将 Map 包装到另一个对象中,例如称为 Payload 并使所有通信成为压缩对象的一部分。

public class Payload<T extends Serializable> {
    private T payload;
    public Payload( T payload ) {
        this.payload = payload;
    }
    private T get() {
        return payload;
    }

  public static final boolean ENABLE_COMPRESSION = BooleanUtils.toBooleanDefaultIfNull( BooleanUtils.toBooleanObject( System.getProperty( "serialization.gzip.enabled" ) ), true );

    private void writeObject( ObjectOutputStream oos ) throws IOException {
        if ( ENABLE_COMPRESSION ) {
            GZIPOutputStream zos = new GZIPOutputStream( oos, 65536 );
            ObjectOutputStream sender = new ObjectOutputStream( zos );
            sender.writeObject( payload );
            sender.flush();
            zos.finish();
        } else {
            oos.defaultWriteObject();
        }
    }

    @SuppressWarnings( "unchecked" )
    private void readObject( ObjectInputStream ois ) throws ClassNotFoundException, IOException {
        if ( ENABLE_COMPRESSION ) {
            GZIPInputStream zis = new GZIPInputStream( ois, 65536 );
            ObjectInputStream receiver = new ObjectInputStream( zis );
            payload = (T) receiver.readObject();
        } else {
            ois.defaultReadObject();
        }
    }
}

然后,当发送任何对象时,它将被包装在一个 Payload 对象中发送并因此被压缩。

public Payload<Map> someRemoteCall() {
    Map map = new HashMap();
    populate( map ); // do whatever needs to be done to fill up the map.
    Payload<Map> payload = new Payload<Map>( map );
    return payload;
}

显然,它可能涉及对接口的一些更改,这可能是不受欢迎的,但到目前为止,这是我找到的最好的。

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多