Netty零拷贝之CompositeByteBuf实际用法
2020-03-12 本文已影响0人
王广帅
Netty所谓的零拷贝就是在数据序列化操作的时候,尽量减少数据的复制。比如将一个byte[]转化为ByteBuf,如果这样写,就会多一次数据的复制:
String a = "ccc";
byte[] bytesSrc = a.getBytes(CharsetUtil.UTF_8);
ByteBuf byteBuf = Unpooled.buffer();
byteBuf.writeBytes(bytesSrc);
这里会将byte[]数组中的数据,复制到ByteBuf内部的数组里面。下面这种方式就是零拷贝:
String a = "ccc";
byte[] bytesSrc = a.getBytes(CharsetUtil.UTF_8);
ByteBuf byteBuf = Unpooled.wrappedBuffer(bytesSrc);
byteBuf.writeBytes(bytesSrc);
这相当于使用已存在的byte[] 数组创建一个ByteBuf,只是对数组有一个引用,ByteBuf的操作,会影响到原来的byte[]。
另外,有时候,如果有两个byte[] 需要转化为一个ByteBuf该怎么办?比如在网络通信中,经常会有Header的ByteBuf和Body的ByteBuf,在发送的时候,需要合成一个ByteBuf。这个时候就该使用CompositeByteBuf,它就像一个容器一样,里面可以包括多个ByteBuf,它是也ByteBuf接口的实现之一。如下面代码所示:
String a = "ccc";
String b = "dddd";
ByteBuf buf1 = Unpooled.wrappedBuffer(a.getBytes(CharsetUtil.UTF_8));
ByteBuf buf2 = Unpooled.wrappedBuffer(b.getBytes(CharsetUtil.UTF_8));
ByteBuf compositeByteBuf = Unpooled.wrappedBuffer(buf1,buf2);
int size = compositeByteBuf.readableBytes();
byte[] bytes = new byte[size];
compositeByteBuf.readBytes(bytes);
String value = new String(bytes,CharsetUtil.UTF_8);
System.out.println("composite buff result : " + value);
如果ByteBuf的数量不确定,还可以这样动态增加ByteBuf:
String a = "ccc";
String b = "dddd";
ByteBuf buf1 = Unpooled.wrappedBuffer(a.getBytes(CharsetUtil.UTF_8));
ByteBuf buf2 = Unpooled.wrappedBuffer(b.getBytes(CharsetUtil.UTF_8));
CompositeByteBuf compositeByteBuf = Unpooled.compositeBuffer();
//compositeByteBuf.addComponent(buf1);//不要使用这个方法,它不会增加writeIndex
compositeByteBuf.addComponent(true,buf1);//一定要使用这个方法
if (buf2 != null) {
compositeByteBuf.addComponent(true, buf2);
}
int size = compositeByteBuf.readableBytes();
byte[] bytes = new byte[size];
compositeByteBuf.readBytes(bytes);
String value = new String(bytes,CharsetUtil.UTF_8);
System.out.println("composite buff result : " + value);
这样在对数据操作的时候,实际上并没有对每个ByteBuf的数据进行复制,在最后向网络层发送数据的时候,会一次性从compositeByteBuf中读取所有的数据,只需要拷贝一次即可。
欢迎关注,谢谢打尝