请戳GitHub原文: github.com/wangzhiwubi…git
更多文章关注:多线程/集合/分布式/Netty/NIO/RPCgithub
MessageToByteEncoder框架可见用户使用POJO对象编码为字节数据存储到ByteBuf。用户只需定义本身的编码方法encode()便可。 首先看类签名:面试
public abstract class MessageToByteEncoder<I> extends
ChannelOutboundHandlerAdapter
复制代码
可知该类只处理出站事件,切确的说是write事件。 该类有两个成员变量,preferDirect表示是否使用内核的DirectedByteBuf,默认为true。TypeParameterMatcher用于检测泛型参数是不是期待的类型,好比说,若是须要编码String类的POJO对象,Matcher会确保write()传入的参数Object的实际切确类型为String。 直接分析write()的处理:promise
public void write(ChannelHandlerContext ctx, Object msg,
ChannelPromise promise) throws Exception {
ByteBuf buf = null;
try {
if (acceptOutboundMessage(msg)) {
I cast = (I) msg;
// 分配一个输出缓冲区
buf = allocateBuffer(ctx, cast, preferDirect);
try {
encode(ctx, cast, buf); // 用户定义的编码方法
} finally {
ReferenceCountUtil.release(cast);
}
if (buf.isReadable()) {
ctx.write(buf, promise); // 确实写入了数据
} else {
// 没有须要写的数据,也有多是用户编码错误
buf.release();
ctx.write(Unpooled.EMPTY_BUFFER, promise);
}
buf = null;
} else {
ctx.write(msg, promise);
}
} catch (EncoderException e) {
throw e;
} catch (Throwable e) {
throw new EncoderException(e);
} finally {
if (buf != null) {
buf.release();
}
}
}
复制代码
编码框架简单明了,再列出allocateBuffer()方法的代码:缓存
protected ByteBuf allocateBuffer(ChannelHandlerContext ctx, I msg,
boolean preferDirect) throws Exception {
if (preferDirect) {
return ctx.alloc().ioBuffer(); // 内核直接缓存
} else {
return ctx.alloc().heapBuffer(); // JAVA队缓存
}
}
复制代码
总的来讲,编码的复杂度大大小于解码的复杂度,这是由于编码不需考虑TCP粘包。编解码的处理还有一个经常使用的类MessageToMessageCodec用于POJO对象之间的转换。若是有兴趣,可下载源码查看。至此,编解码框架已分析完毕。bash
请戳GitHub原文: https://github.com/wangzhiwubigdata/God-Of-BigData
关注公众号,内推,面试,资源下载,关注更多大数据技术~
大数据成神之路~预计更新500+篇文章,已经更新60+篇~ 复制代码