想要写个Rpc框架,先把demo跑起来吧
思考一下我们的demo需要实现哪些功能
- 远程(两台虚拟机之间的方法调用)
- 制定统一的消息POJO
- 使用Netty实现通信
- 利用反射来获取执行结果,并回传
- POJO对象序列化的实现
废话不多说,先上已经写完的demo目录结构
关于Netty的用法此处不再赘述,下面贴上编码解码器及消息POJO代码(demo中使用JAVA自带的序列化)
解码器:
package com.fastRPC.serialization;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.ByteToMessageDecoder;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import java.io.ByteArrayInputStream;
import java.io.ObjectInputStream;
import java.util.List;
//解码器
public class DefaultDecoder extends ByteToMessageDecoder {
@Override
protected void decode(ChannelHandlerContext channelHandlerContext, ByteBuf byteBuf, List<Object> list) throws Exception {
if(byteBuf.readableBytes()<4)return;
byteBuf.markReaderIndex();//标记读取的位置,如果发现缓冲区并没有足够长度的字节,则放弃本次读取
int length = byteBuf.readInt();
if(length<0){
channelHandlerContext.close();
}
if(byteBuf.readableBytes()<length){
byteBuf.resetReaderIndex();
return;
}
//开始读取并反序列化成Object
byte[] body = new byte[length];
byteBuf.readBytes(body);
ObjectInputStream oi = new ObjectInputStream(new ByteArrayInputStream(body));
Object object = oi.readObject();
list.add(object);
}
}
编码器:
package com.fastRPC.serialization;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.MessageToByteEncoder;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
public class DefaultEncoder extends MessageToByteEncoder {
@Override
protected void encode(ChannelHandlerContext channelHandlerContext, Object o, ByteBuf byteBuf) throws Exception {
ByteArrayOutputStream ba = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(ba);
oos.writeObject(o);
byte[] body = ba.toByteArray();
//直接将byte写入byteBuf即可(最前面4个字节需要写入一个Int型数据,代表数组长度)
byteBuf.writeInt(body.length);
byteBuf.writeBytes(body);
}
}
消息Bean
省略Getter和Setter
public class MessageRequest implements Serializable {
private String messageId;
private String className;
private String methodName;
private Class<?>[] typeParameters;
private Object[] parameters;
}
public class MessageResponse implements Serializable {
private String messageId;
private String error;
private Object result;
}
以及我们要被调用的方法
返回一个随机数
public class EchoRandomServiceImpl implements EchoRandomService {
@Override
public String echo() {
return String.valueOf(Math.random());
}
}
具体的POJO封装就不用写了。
启动服务端
启动客户端
测试成功!
基本的Demo已经完成
接下来的工作就是对功能的拓展了!
- 序列化可以集成其他序列化框架
- 引入zookeeper并实现服务的注册
- 部署多实例进行测试
- 进一步提升性能