5.netty集成messagePack序列化框架
来源:互联网 发布:佳能打印机清零软件 编辑:程序博客网 时间:2024/05/29 03:18
1.介绍
总所周知jdk提高的序列化效率上面说备受诟病主要是这几点:
无法跨语言:别的语言不能将byte数组反序列化。而RPC框架往往需要跨语言调用
编码后的码流太大:jdk序列化后编码生成的二进制数据太大
编解码性能太低:jdk序列化和发序列化速度太慢
所以业界提供了一些序列化框架。其中的MessagePack是一个高效的二进制序列化框架,和json一样支持不同语言间数据交换,性能更快、码流更小等优点
所需依赖:
<!-- netty依赖all --><dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0.0.Alpha1</version></dependency><!-- msgpack --><dependency> <groupId>org.msgpack</groupId> <artifactId>msgpack</artifactId> <version>0.6.6</version></dependency><!-- javassist --><dependency> <groupId>javassist</groupId> <artifactId>javassist</artifactId> <version>3.9.0.GA</version></dependency>
2.netty实现
对象序列化编码器:
package com.tyf.netty;import org.msgpack.MessagePack;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.codec.MessageToByteEncoder;//开发自定编码器public class myEncoder extends MessageToByteEncoder<Object> {@Overrideprotected void encode(ChannelHandlerContext ctx, Object obj, ByteBuf buf) throws Exception {MessagePack msgPack = new MessagePack();//序列化操作byte[] bytes = msgPack.write(obj);//netty操作,将对象序列化数组传入ByteBufbuf.writeBytes(bytes);}}对象反序列化解码器:
package com.tyf.netty;import java.util.List;import org.msgpack.MessagePack;import io.netty.buffer.ByteBuf;import io.netty.channel.ChannelHandlerContext;import io.netty.handler.codec.MessageToMessageDecoder;public class myDecoder extends MessageToMessageDecoder<ByteBuf> {@Overrideprotected void decode(ChannelHandlerContext ctx, ByteBuf buf, List<Object> objs) throws Exception {final byte[] bytes;final int length = buf.readableBytes();bytes = new byte[length];//从数据包buf中获取要操作的byte数组buf.getBytes(buf.readerIndex(), bytes,0,length);//将bytes反序列化成对象,并添加到解码列表中MessagePack msgpack = new MessagePack();objs.add(msgpack.read(bytes));}}
server:
添加编解码器、粘包拆包解码器
package com.tyf.netty;import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.ChannelHandler.Sharable;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.DelimiterBasedFrameDecoder;import io.netty.handler.codec.FixedLengthFrameDecoder;import io.netty.handler.codec.LengthFieldBasedFrameDecoder;import io.netty.handler.codec.LengthFieldPrepender;import io.netty.handler.codec.string.StringDecoder;@Sharablepublic class MyServerHandler extends ChannelHandlerAdapter {@Overridepublic void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception{//直接获取request的msgSystem.out.println("消息:"+(person)msg);}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {super.exceptionCaught(ctx, cause);}//创建起步程序public static void main(String [] argsStrings) throws Exception {//配置服务端NIO线程组(boss线程、worker线程)EventLoopGroup bGroup = new NioEventLoopGroup();EventLoopGroup wGroup = new NioEventLoopGroup();//创建启动辅助类ServerBootstrap bootstrap = new ServerBootstrap();bootstrap.group(bGroup, wGroup) .channel(NioServerSocketChannel.class) .option(ChannelOption.TCP_NODELAY, true) .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000) .childHandler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel channel) throws Exception {//添加对象系列化编解码器,同时提供粘包拆包支持channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2,0,2));channel.pipeline().addLast("对象解码器",new myDecoder());channel.pipeline().addLast(new LengthFieldPrepender(2));channel.pipeline().addLast("对象编码器",new myEncoder());channel.pipeline().addLast(new MyServerHandler());} });try {//监听本地端口,同步等待监听结果ChannelFuture future = bootstrap.bind(11111).sync();//等待服务端监听端口关闭,优雅退出future.channel().closeFuture().sync();}finally {bGroup.shutdownGracefully();wGroup.shutdownGracefully();} }
client:
package com.tyf.netty;import io.netty.bootstrap.Bootstrap;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.FixedLengthFrameDecoder;import io.netty.handler.codec.LengthFieldBasedFrameDecoder;import io.netty.handler.codec.LengthFieldPrepender;import io.netty.handler.codec.string.StringDecoder;public class MyClientHandler extends ChannelHandlerAdapter {@Overridepublic void channelActive(ChannelHandlerContext ctx) throws Exception {//创建三个对象person p1 = new person("name1",1);person p2 = new person("name2",2);person p3 = new person("name3",3);person p4 = new person("name4",4);person p5 = new person("name5",5);//writectx.write(p1);ctx.write(p2);ctx.write(p3);ctx.write(p4);ctx.write(p5);//flushctx.flush();}@Overridepublic void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {super.exceptionCaught(ctx, cause);}//创建起步程序public static void main(String [] argsStrings) throws Exception {//配置客户端端NIO线程组EventLoopGroup bGroup = new NioEventLoopGroup();//创建客户端启动辅助类Bootstrap bootstrap = new Bootstrap();bootstrap.group(bGroup). channel(NioSocketChannel.class). option(ChannelOption.TCP_NODELAY, true). option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 3000). handler(new ChannelInitializer<SocketChannel>() {@Overrideprotected void initChannel(SocketChannel channel) throws Exception {//添加对象系列化编解码器,同时提供粘包拆包支持channel.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2,0,2));channel.pipeline().addLast("对象解码器",new myDecoder());channel.pipeline().addLast(new LengthFieldPrepender(2));channel.pipeline().addLast("对象编码器",new myEncoder());channel.pipeline().addLast(new MyClientHandler());} });//发起异步连接ChannelFuture future = bootstrap.connect("127.0.0.1", 11111).sync();try {//等待客户端链路关闭future.channel().closeFuture().sync();} finally {//优雅退出,释放资源bGroup.shutdownGracefully();} }}
阅读全文