Netty进阶之路-MessagePack编解码

快来打我* 2022-02-05 07:23 384阅读 0赞

Netty进阶之路-MessagePack编解码

  • 前言
  • MessagePack优点
  • Netty客户端—MessagePack编解码
    • Netty客户端—MessagePack编码
    • Netty客户端—MessagePack解码
    • Netty客户端—编解码使用
  • Netty服务端—MessagePack编解码
    • Netty服务端—MessagePack解码
    • Netty服务端—MessagePack编码
    • Netty服务端—编解码使用

前言

之前的Netty利用json和LineBasedFrameDecoder和StringDecoder来实现数据传输和解决粘包/半包问题。后来发现Netty支持更高效的编解码例如MessagePack。本篇主要来讲讲MessagePack的使用。

MessagePack优点

MessagePack是一个高效的二进制序列化框架

  1. 和json一样支持跨语言
  2. 序列化之后的码流更小
  3. 编解码性能高效

Netty客户端–MessagePack编解码

Netty提供了丰富的编解码器抽象基类,我们可以很容易的实现这些基类来自定义编解码器。

Netty客户端–MessagePack编码

这里将需要编码的对象加上@Message注解
我之前 result属性用的是Object 因为返回类型可能是List或者Map或者String等但是在MessagePack中不能使用Object 类型 所有我改成了String。

  1. @Message
  2. public class RPCRequest {
  3. private String requestID;
  4. private String className;
  5. private String methodName;
  6. private String[] parameters;
  7. private String result;
  8. public String getRequestID() {
  9. return requestID;
  10. }
  11. public void setRequestID(String requestID) {
  12. this.requestID = requestID;
  13. }
  14. public String getClassName() {
  15. return className;
  16. }
  17. public void setClassName(String className) {
  18. this.className = className;
  19. }
  20. public String getMethodName() {
  21. return methodName;
  22. }
  23. public void setMethodName(String methodName) {
  24. this.methodName = methodName;
  25. }
  26. public String[] getParameters() {
  27. return parameters;
  28. }
  29. public void setParameters(String[] parameters) {
  30. this.parameters = parameters;
  31. }
  32. public String getResult() {
  33. return result;
  34. }
  35. public void setResult(String result) {
  36. this.result = result;
  37. }
  38. }

利用Netty基类来自定义编码器

  1. public class ClientMsgPackEncode extends MessageToByteEncoder<Object>{
  2. @Override
  3. protected void encode(ChannelHandlerContext arg0, Object msg, ByteBuf out)
  4. throws Exception {
  5. RPCRequest request = (RPCRequest) msg;
  6. MessagePack msgPack = new MessagePack();
  7. //msgPack.register(RPCRequest.class);
  8. byte[] raw = null;
  9. raw = msgPack.write(request);
  10. out.writeBytes(raw);
  11. }
  12. }

Netty客户端–MessagePack解码

  1. @Message
  2. public class RPCResponse {
  3. private String requestID;
  4. private String result;
  5. public String getRequestID() {
  6. return requestID;
  7. }
  8. public void setRequestID(String requestID) {
  9. this.requestID = requestID;
  10. }
  11. public String getResult() {
  12. return result;
  13. }
  14. public void setResult(String result) {
  15. this.result = result;
  16. }
  17. }

利用Netty基类来自定义解码器

  1. public class ClientMsgPackDecode extends MessageToMessageDecoder<ByteBuf>{
  2. @Override
  3. protected void decode(ChannelHandlerContext arg0, ByteBuf msg,
  4. List<Object> out) throws Exception {
  5. // TODO Auto-generated method stub
  6. final byte[] array;
  7. final int length = msg.readableBytes();
  8. array = new byte[length];
  9. msg.getBytes(msg.readerIndex(), array, 0, length);
  10. MessagePack msgPack = new MessagePack();
  11. out.add(msgPack.read(array,RPCResponse.class));
  12. }
  13. }

Netty客户端–编解码使用

在链路里添加

  1. ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2,0,2));
  2. ch.pipeline().addLast(new LengthFieldPrepender(2));
  3. ch.pipeline().addLast(new ClientMsgPackEncode());//编码
  4. ch.pipeline().addLast(new ClientMsgPackDecode());//解码
  5. ch.pipeline().addLast(new RPCRequestHandler());//添加相应回调处理和编解码器

之后的发送消息和读取消息可以直接使用对象

Netty服务端–MessagePack编解码

说明一下 客户端服务端用了2套的原因是编解码的时候对象不是同一个
例如客户端编码是RPCRequest对象 服务端编码RPCResponse 对象。

Netty服务端–MessagePack解码

  1. public class ServerMsgPackDecode extends MessageToMessageDecoder<ByteBuf>{
  2. @Override
  3. protected void decode(ChannelHandlerContext arg0, ByteBuf msg,
  4. List<Object> out) throws Exception {
  5. // TODO Auto-generated method stub
  6. final byte[] array;
  7. final int length = msg.readableBytes();
  8. array = new byte[length];
  9. msg.getBytes(msg.readerIndex(), array, 0, length);
  10. MessagePack msgPack = new MessagePack();
  11. out.add(msgPack.read(array,RPCRequest.class));
  12. }
  13. }

Netty服务端–MessagePack编码

  1. public class ServerMsgPackEncode extends MessageToByteEncoder<Object>{
  2. @Override
  3. protected void encode(ChannelHandlerContext arg0, Object msg, ByteBuf out)
  4. throws Exception {
  5. RPCResponse RPCResponse = (RPCResponse) msg;
  6. MessagePack msgPack = new MessagePack();
  7. //msgPack.register(RPCResponse.class);
  8. byte[] raw = null;
  9. raw = msgPack.write(RPCResponse);
  10. out.writeBytes(raw);
  11. }
  12. }

Netty服务端–编解码使用

同样在链路里添加

  1. socketChannel.pipeline().addLast(new LengthFieldBasedFrameDecoder(65535, 0, 2,0,2));//编码
  2. socketChannel.pipeline().addLast(new LengthFieldPrepender(2));
  3. socketChannel.pipeline().addLast(new ServerMsgPackEncode());//编码
  4. socketChannel.pipeline().addLast(new ServerMsgPackDecode());//解码
  5. socketChannel.pipeline().addLast(new RPCResponseHandler());//处理类

发表评论

表情:
评论列表 (有 0 条评论,384人围观)

还没有评论,来说两句吧...

相关阅读

    相关 Netty4解码

    本文是基于Netty4.1.x,一般在使用Netty作为网络框架进行开发时,编解码框架是我们应该注意的一个重要部分。应用从网络层接收数据需要经过解码(Decode),将二进制的