netty(5)–序列化
序列化问题
Java 序列化的目的主要有两个:
? 当选行远程跨迸程服务调用时,需要把被传输的 Java 对象编码为字节数组或者ByteBuffer 对象。而当远程服务读取到 ByteBuffer 对象或者字节数组时,需要将其解码为发送时的 Java 对象。这被称为 Java 对象编解码技术。 ? Java 序列化仅仅是 Java 编解码技术的一种,由于它的种种缺陷,衍生出了多种编解码 技术和框架
Java 序列化的缺点
? Java 序列化从 JDK1.1 版本就已经提供,它不需要添加额外的类库,只需实现java.io.Serializable 并生成序列 ID 即可,因此,它从诞生之初就得到了广泛的应用。但是在远程服务调用(RPC)时,很少直接使用 Java 序列化进行消息的编解码和传输,这又是什么原因呢?下面通过分析.Tava 序列化的缺点来找出答案。
-
无法跨语言 对于跨进程的服务调用,服务提供者可能会使用 C 十+或者其他语言开发,当我们需要和异构语言进程交互时 Java 序列化就难以胜任。由于 Java 序列化技术是 Java 语言内部的私有协议,其他语言并不支持,对于用户来说它完全是黑盒。对于 Java 序列化后的字节数组,别的语言无法进行反序列化,这就严重阻碍了它的应用。 -
序列化后的码流太大 通过一个实例看下 Java 序列化后的字节数组大小。 -
序列化性能太低 无论是序列化后的码流大小,还是序列化的性能,JDK 默认的序列化机制表现得都很差。因此,我们边常不会选择 Java 序列化作为远程跨节点调用的编解码框架。
常用序列化
JBoss Marshalling
public class MarshallingInitializer extends ChannelInitializer<Channel> {
private final MarshallerProvider marshallerProvider;
private final UnmarshallerProvider unmarshallerProvider;
public MarshallingInitializer(UnmarshallerProvider unmarshallerProvider,
MarshallerProvider marshallerProvider) {
this.marshallerProvider = marshallerProvider;
this.unmarshallerProvider = unmarshallerProvider;
}
@Override
protected void initChannel(Channel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
pipeline.addLast(new MarshallingDecoder(unmarshallerProvider));
pipeline.addLast(new MarshallingEncoder(marshallerProvider));
pipeline.addLast(new ObjectHandler());
}
public static final class ObjectHandler extends SimpleChannelInboundHandler<Serializable> {
@Override
public void channelRead0(ChannelHandlerContext channelHandlerContext, Serializable serializable)
throws Exception {
}
}
}
Protocol Buffers
public class ProtoBufInitializer extends ChannelInitializer<Channel> {
private final MessageLite lite;
public ProtoBufInitializer(MessageLite lite) {
this.lite = lite;
}
@Override
protected void initChannel(Channel ch) throws Exception {
ChannelPipeline pipeline = ch.pipeline();
pipeline.addLast(new ProtobufVarint32FrameDecoder());
pipeline.addLast(new ProtobufEncoder());
pipeline.addLast(new ProtobufDecoder(lite));
pipeline.addLast(new ObjectHandler());
}
public static final class ObjectHandler extends SimpleChannelInboundHandler<Object> {
@Override
public void channelRead0(ChannelHandlerContext ctx, Object msg) throws Exception {
}
}
}
MessagePack
|