@Data
public abstract class Packet<ID> {
private transient byte version = 1;
public abstract ID getRequestId();
public abstract void setRequestId(ID id);
}
解码器:
public class PacketDecoder extends ByteToMessageDecoder {
private static final PacketCodec codec = PacketCodec.INSTANCE;
@Override
protected void decode(ChannelHandlerContext ctx, ByteBuf in, List<Object> out) throws Exception {
Packet packet = codec.decode(in);
out.add(packet);
}
}
编码器:
public class PacketEncoder extends MessageToByteEncoder<Packet> {
private static final PacketCodec codec = PacketCodec.INSTANCE;
@Override
protected void encode(ChannelHandlerContext ctx, Packet msg, ByteBuf out) throws Exception {
out.writeBytes(codec.encode(msg));
}
}
RPC 请求 & 响应信息
请求:
@EqualsAndHashCode(callSuper = false)
@Data
@Builder
public class RpcRequestPacket extends Packet<Long> {
private Class clazz;
private String methodName;
private Object[] parameters;
private Class[] parameterTypes;
private Long requestId;
}
RPC 实现笔记(一)
简单来说就是实现一个工具,使得两个不同(也可以相同)服务器的程序能够互相调用函数。
首先,实现服务端与客户端的通信
实现基于TCP的服务端与客户端通信
相关技术:
需要实现的大致流程
所以,需要的组件:
注:其中
服务端 & 客户端
可以参考Netty学习笔记(一)、(二)序列化 & 反序列化:protostuff
protostuff
使用起来极为方便,参考 github 上的代码示例即可。
编码器 & 解码器
首先,定义一个通信中使用的数据格式也可称为协议(protocol)
然后根据我们定义的数据格式,实现我们的编解码工具
数据格式
固定长度(首部):
不定长(数据):
编解码工具
备注:由于无法直接序列化
Class
对象,因此用PacketInfo
包装了一下Packet.java
:解码器:
编码器:
RPC 请求 & 响应信息
请求:
以上成员属性除
requestId
外均是提供动态代理使用的属性,即调用某个类的某个方法名,以及此方法需要的参数列表和对应参数类型列表。requestId
:用于客户端关联异步执行的 RPC 请求与结果,服务端不做任何操作,直接返回即可。响应: