手写RPC框架之网络传输协议设计及实现

本文详细介绍了在自定义RPC框架中,网络传输协议的设计,包括数据包的结构、各字段含义,以及如何利用Netty进行数据的编码和解码,以解决粘包等问题。通过 RpcMessage 实体类和 RpcMessageEncoder、RpcMessageDecoder 的实现,展示了整个数据传输过程。
摘要由CSDN通过智能技术生成

本文主要介绍my-rpc框架中网络传输数据的格式设计,以及如何在发送和接收数据的过程中进行的编解码过程。

网络传输协议设计

数据在网络中是以字节(二进制)的形式传输的,要让通信的双方都能正确的接收对方发送的信息,一定要定义好数据格式,要让对方知道如何解析,从哪一位开始到哪一位代表什么含义,数据的总长度是多少,以避免多读或少读发生解析错误和粘包等问题。

参考TCP协议对TCP数据包的设计,以下是my-rpc框架设计的网络传输的数据包(my-rpc-package)格式,分为headerbody两部分:

		 *   0     1     2     3     4        5     6     7     8         9          10      11     12  13  14   15 16
		 *   +-----+-----+-----+-----+--------+----+----+----+------+-----------+-------+----- --+-----+-----+-------+
header	 *   |   magic   code        |version | full length         | messageType| codec|compress|    RequestId      |
		 *   +-----------------------+--------+---------------------+-----------+-----------+-----------+------------+
		 *   |                                                                                                       |
body	 *   |                                         body                                                          |
		 *   |                                                                                                       |
		 *   |                                        ... ...                                                        |
		 *   +-------------------------------------------------------------------------------------------------------+
		 * 4B  magic code(魔法数)   1B version(版本)   4B full length(消息长度)    1B messageType(消息类型)
		 * 1B codec(序列化类型) 1B compress(压缩类型)    4B  requestId(请求的Id)
		 * body(object类型数据)
  • 魔数,4个字节,主要是为了筛选来到服务端的数据包,有了这个魔数之后,服务端首先取出前面四个字节进行比对,能够在第一时间识别出这个数据包并非是遵循自定义协议的,也就是无效数据包,为了安全考虑可以直接关闭连接以节省资源。
  • 版本号,1个字节,为版本升级预留
  • 消息长度,4个字节,包括header和body的总长度
  • 消息类型,1个字节,请求/响应/心跳检测请求/心跳检测响应,根据消息类型来确定body反序列化后的实体类
  • 序列化类型,1个字节,body数据的序列化方式(header不序列化)
  • 压缩类型,1个字节,body数据的压缩方式(header不压缩)
  • requestId,4个字节,标识该次请求的编号
  • body,真正传输的数据

网络传输实体设计

RpcMessage.java 是根据my-rpc-package数据包设计的对应的实体类,是my-rpc通用的网络传输对象(DTO)

@Builder
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
public class RpcMessage {
   
    // 消息类型
    private byte messageType;  
    // 序列化类型 : kryo  protostuff
    private byte codec;  
    // 压缩类型  gzip  
    private byte compress;
    // 标识该次消息的编号   
    private int requestId;
    // 具体的传输数据  
    private Object data;
}

根据消息类型的不同,body主要分为两类,请求RpcRequest响应RpcResponse

RpcRequest.java
请求中应该包含远程调用的类名、方法名以及参数等信息。

@Setter
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class RpcRequest  {
   
    private String requestId;  // 该次request的id
    private String interfaceName; // 接口全限定名
    private String methodName;  // 方法名
    private Object[] parameters;  // 参数 
    private Class<?>[] paraTypes;  // 参数类型
    private String group;  // 一个接口的多种实现由group区分

    public RpcServiceProperties toRpcProperties() {
   
        return RpcServiceProperties.builder().serviceName(this.getInterfaceName()).group(this.getGroup())
                .build();
    }
}

请求类中还有一个RpcServiceProperties类,该类包含接口名字和group分组两个信息,这两个信息能完全定位一个具体接口实现类,服务消费端也是根据toRpcServiceName()方法返回值去服务注册中心找到服务提供方的ip地址。

@Getter
@Setter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值