序列化后的消息负载大于其应有的负载



摘要

我正在尝试通过Spring Integration应用程序代理TCP流流量。我有一个测试负载,它是一个字节数组,总共291字节长。前两个字节是十六进制的长度头,其余289个字节是数据本身。

最初,我使用的是头值为2的ByteArrayLengthHeaderSerializerTcpNetServerConnectionFactory

该消息由连接到我的TcpNetServerConnectionFactoryTcpReceivingChannelAdapter接收。它被放在一个通道上,直接连接到ServiceActivator,后者接收Message对象作为参数。

在该方法中,我使用message.getPayload()检索有效载荷,然后将该Object交给SerializationUtils.serialize()以返回字节数组。当我打印array.length时,它是316,而不是289。

为什么有效载荷更大?我不明白这些额外的字节是什么,我不能将其代理到上游,因为它现在的格式不正确。

背景

我的第一个想法是,2字节的标头格式不正确,无法与ByteArrayLengthHeaderSerializer一起使用。所以可以肯定的是,我扩展了那个类并自己实现了readHeader()。正如你所看到的,我将长度打印到System.err,它如预期的那样工作——我得到289。

但是,当我在Service Activator中转换/打印有效负载大小时,有效负载大小仍然高于300。在我的序列化程序和Service Activator之间没有其他消息传递端点,所以我再次不明白这些额外的字节是从哪里来的。

在这种情况下,ByteArrayLengthHeaderSerializer可能工作正常,因为我仍然有这个问题,尽管我已经确认在它到达Service Activator之前长度是289。

不管我使用哪一个序列化程序,有效负载大小是如何增加的?

代码

自定义ByteArrayLengthHeaderSerializer

@Override
protected int readHeader(InputStream inputStream) throws IOException {
byte[] lengthPart = new byte[2];
if (inputStream.read(lengthPart, 0, 2) != 2) {
throw new IOException();
}
int length = ByteBuffer.wrap(lengthPart).getShort();
System.err.println(length);
return length;
}

Service Activator方法

public Message editRequest(Message message) {
byte[] payload = SerializationUtils.serialize(message.getPayload());
System.err.println("payload length: " + payload.length);
return message;
}

集成组件

<int:channel id="requestChannelPreEdit">
<int:queue capacity="100"/>
</int:channel>
<int:poller id="defaultPoller"
default="true"
fixed-delay="50"
receive-timeout="5000">
</int:poller>
<bean id="headerSerializer"
class="CustomByteArrayLengthHeaderSerializer">
</bean>
<int-ip:tcp-connection-factory id="serverFactory"
type="server"
port="6060"
serializer="headerSerializer"
deserializer="headerSerializer"/>
<int-ip:tcp-inbound-channel-adapter id="inboundRequestAdapter"
channel="requestChannelPreEdit"
connection-factory="serverFactory"/>
<bean id="requestEditor"
class="RequestEditor"/>
<int:service-activator id="requestEditorSA"
input-channel="requestChannelPreEdit"
ref="requestEditor"
method="editRequest"/>

,然后将该对象交给SerializationUtils.serialize()以返回字节数组

byte[] payload = SerializationUtils.serialize(message.getPayload());

根本没有必要这么做;有效载荷已经是CCD_ 16(由长度报头串行器创建)。

当然,将序列化应用于现有的byte[]最终会变得更大,因为它添加了元数据(幻数、类型信息等)。

只需将服务更改为

public Message editRequest(Message<byte[]> message) {
byte[] payload = message.getPayload();
...
}

最新更新