如果将消息看作是对于特定的应用程序具有具体含义的结构化的字节序列—它的数据。那么编码器是将消息转换为适合于传输的格式(最有可能的就是字节流);而对应的解码器则是将网络字节流转换回应用程序的消息格式。
在了解Netty编解码之前,先了解Java的编解码:
- 编码(Encode)称为序列化, 它将对象序列化为字节数组,用于网络传输、数据持久化或者其它用途。
- 解码(Decode)称为反序列化,它把从网络、磁盘等读取的字节数组还原成原始对象(通常是原始对象的拷贝),以方便后续的业务逻辑操作。
java序列化对象只需要实现java.io.Serializable接口并生成序列化ID,这个类就能够通过java.io.ObjectInput和java.io.ObjectOutput序列化和反序列化。
- Java序列化目的:① 网络传输。② 对象持久化。
- Java序列化缺点:① 无法跨语言。 ② 序列化后码流太大。③ 序列化性能太低。
Java序列化仅仅是Java编解码技术的一种,由于它的种种缺陷,衍生出了多种编解码技术和框架,这些编解码框架实现消息的高效序列化,如KryoSerializer、HessianSerializer。
通过以下代码比较:
public static void main(String[] args)throws IOException {
StudentInfo studentInfo=new StudentInfo(); // StudentInfo类已实现java.io.Serializable接口
studentInfo.setUserName("Kosamino");
studentInfo.setAge(25);
studentInfo.setSex("男");
// 序列化和反序列化在大量IO的情况下是极其耗费性能的,因此其性能就集中体现在序列化后大小以及序列化所消耗的时间
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream os = new ObjectOutputStream(bos);
os.writeObject(info);
os.flush();
os.close();
byte[] b = bos.toByteArray();
System.out.println("The jdk serializable length is : " + b.length);
byte[] k=KryoSerializer.serialize(studentInfo);
System.out.println("The kryo serializable length is : "+k.length);
byte[] h= HessianSerializerUtil.serialize(studentInfo);
System.out.println("The Hessian serializable length is : "+h.length);
}
根据以上输出:
The jdk serializable length is : 164 // JDK自带序列化/反序列化性能最低
The kryo serializable length is : 61
The Hessian serializable length is : 99
JDK自带的序列化/反序列化效率极其低下,因此推荐使用一些高效框架。
概念
在网络应用中需要实现某种编解码器,将原始字节数据与自定义的消息对象进行互相转换。网络中都是以字节码的数据形式来传输数据的,服务器编码数据后发送到客户端,客户端需要对数据进行解码。
netty提供了强大的编解码器框架,使得我们编写自定义的编解码器很容易,也容易封装重用。对于Netty而言,编解码器由两部分组成:编码器、解码器。
- 解码器:负责将消息从字节或其他序列形式转成指定的消息对象。
- 编码器:将消息对象转成字节或其他序列形式在网络上传输。
Netty 的编(解)码器实现了 ChannelHandlerAdapter,也是一种特殊的 ChannelHandler,所以依赖于 ChannelPipeline,可以将多个编(解)码器链接在一起,以实现复杂的转换逻辑。
Netty里面的编解码:
- 解码器:负责处理“入站 InboundHandler”数据,如MessageToMessageDecoder和ByteToMessageDecoder。
- 编码器:负责“出站 OutboundHandler” 数据,如MessageToMessageEncoder和MessageToByteEncoder。
解码器(Decoder)