【BlossomRPC】如何自定义一个RPC协议?

146 阅读3分钟

RPC项目

配置中心项目

网关项目

如何设计一个RPC协议?

在上面的需求描述中我们知道,RPC非常重要的一环,就是自己制定符合自己需求的通信协议,这里,我简单的列出了我的协议。

public class RpcHeader implements Serializable {
    //public static final long serialVersionUID = 200201141215L;
    //当前RPC服务版本号(借鉴Dubbo)
    private byte versionId;

    //使用的序列化/压缩算法
    private byte algorithmType;

    //请求类型
    private byte reqType;

    //请求ID
    private long reqId;

    //消息内容长度
    private int length;

}
//RPC DTO对象
//是项目最终使用的数据传输对象
@Data
public class RpcDto<T> implements Serializable {
    //请求头
    private RpcHeader header;

    //数据
    private T data;
}

协议的实现比较简单,但是,那些设计的非常良好的开源框架,也会在协议上下很多功夫,来尽可能保证使用的协议传输快,性能好,空间浪费少。 这里我简单的列出一个对协议的优化方式。 比如我们知道,对于algorithmType这个字段,使用byte类型能最多提供8bit,也就是最多256种不同方式。 那么,其实单纯的使用一个byte,我们就能同时表示出要使用的序列化算法和压缩等算法,也就是用位运算这种方法,能够充分的解决空间的浪费问题同时位运算性能也很高。 具体设计方式如下:

package blossom.project.rpc.common.enums;

/**
 * @author: ZhangBlossom
 * @date: 2023/12/16 16:55
 * @contact: QQ:4602197553
 * @contact: WX:qczjhczs0114
 * @blog: https://blog.csdn.net/Zhangsama1
 * @github: https://github.com/ZhangBlossom
 * AlgorithmTypeEnum类
 * 一个字节8个bit 0000 | 0000
 * 2^4 = 16 也就是高低位分别可以对应16种数据
 * 1:可以高位用于存放压缩算法
 * 2:低位存储序列化算法
 * 3:使用位运算进行高低位计算即可得到具体的算法类型
 */
public enum AlgorithmTypeEnum {

    // 压缩算法枚举定义
    NO_COMPRESSION((byte)0x00), // 无压缩(默认操作,这样子就算不选也无所谓了)
    GZIP((byte)0x10),           // GZIP压缩
    // ... 其他压缩算法

    // 序列化算法枚举定义
    PROTOBUF((byte)0x01),       // Protobuf序列化
    ARVO((byte)0x02),           // Avro序列化
    JSON((byte)0x03),           // JSON序列化
    JAVA((byte)0x04);           // Java原生序列化

    private byte code;

    AlgorithmTypeEnum(byte code) {
        this.code = code;
    }

    public byte getCode() {
        return this.code;
    }

    // 结合压缩算法和序列化算法的code
    public static byte combine(AlgorithmTypeEnum compression, AlgorithmTypeEnum serialization) {
        return (byte) (compression.code | serialization.code);
    }

    // 分离组合code为压缩和序列化算法的code
    public static AlgorithmTypeEnum[] split(byte combinedCode) {
        byte compressionCode = (byte) (combinedCode & 0xF0); // 获取高4位
        byte serializationCode = (byte) (combinedCode & 0x0F); // 获取低4位

        return new AlgorithmTypeEnum[]{
                findByCode(compressionCode), // 压缩算法
                findByCode(serializationCode) // 序列化算法
        };
    }

    // 根据code查找对应的枚举值
    private static AlgorithmTypeEnum findByCode(byte code) {
        for (AlgorithmTypeEnum type : AlgorithmTypeEnum.values()) {
            if (type.code == code) {
                return type;
            }
        }
        //没有找到对应的枚举类型就报错
        throw new RuntimeException("No enumeration type was found");
    }
}

然,在协议上还有很多功夫可以去琢磨,我就不细扣了。