一个简易的rpc框架,别的先不多说上github
https://github.com/cao2068959/chyrpc20
注册中心 : zookeeper (使用curator 操作)
通信框架 : netty (4.1.25版本)
序列化 : kryo
以下只写了大体项目流程,以及展示部分代码,具体请点击上方github ,代码里基本都写了注释
本RPC框架,有一个统一的 框架容器,用来初始化,zookeeper的连接,以及缓存一些远程服务.这样方便负载均衡调用,以及不用每次调用都去zookeeper上获取远程服务器,如果远程服务器挂机,或者添加新的远程服务器,使用watch机制,刷新到缓存中.
//创造RPC应用容器,建议使用单列
ChyRpcApplication chyRpcApplication = new ChyRpcApplication();
//如果有提供者,设置一个通信端口,等待调用者来访问
chyRpcApplication.setPort(7777);
//把服务注册进RPC容器,信息写入zk,
//参数1是服务唯一的名字
//参数2的实例对象,将会被缓存进application容器,如果调用者请求,将会反射执行
//UserServiceImp实现了接口UserService
chyRpcApplication.register("nameIsNull",new UserServiceImp());
//也能这么注册,只是注册的名字是UserService接口的全路径
chyRpcApplication.register(UserService.class,new UserServiceImp());
//根据服务的名字,去zk中获取当前提供了该远程服务的IP地址和端口,存入缓存
//同时开启watch,如果该远程服务的提供者变动,ZK将会推送,然后刷新缓存
//生成代理对象,用的JDK动态代理.
UserService service = chyRpcApplication.getService("nameIsNull",UserService.class);
//执行了动态代理的代理方法,将会调用netty去发送请求.
//参数和返回值,讲会使用kryo去序列化,然后tcp传输
service.xx(...)
注意点:
@Override
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
//如果调用object默认方法,就放行
if (Object.class.equals(method.getDeclaringClass())) {
return method.invoke(this, args);
}
//调用模版方法,正真远程调用
Object result = doRPCHandle(remoteServices, method, args);
return result;
}
在动态代理的时候,一定要过滤了 object的 自带方法.不然在整合spring的时候,spring会自动调用equals() 方法,导致异常
netty这边,没什么好说的.重点在于,管道的使用
服务提供者 :
EventLoopGroup work = new NioEventLoopGroup();
EventLoopGroup child = new NioEventLoopGroup();
//SerializationHandle serializationHandle = new SerializationHandle();
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(work,child)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();
//发送数据的时候,加上包的长度.
pipeline.addLast(new LengthFieldPrepender(4));
//接收数据的时候,把包的长度拆了
pipeline.addLast(new LengthFieldBasedFrameDecoder(pageLen,0,4,0,4));
//把发送出去的数据 序列化(使用kryo)
pipeline.addLast( new SerializationHandle());
//把接收的数据序列化(使用kryo)
pipeline.addLast(new UnSerializationHandle());
//服务端自己的业务逻辑
pipeline.addLast(new RrcServiceChannel());
}
});
ChannelFuture channelFuture = null;
try {
channelFuture = serverBootstrap.bind(port).sync();
System.out.println(ip+":"+port+" : 服务开启");
//channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
// work.shutdownGracefully();
// child.shutdownGracefully();
}
调用者,和提供者,类似.
框架介绍,到此就结束了.一个很简单的RPC框架.具体实现细节.请移步github,代码上都有注释
这里封装成了对应的 starter 请移步下一篇博文
https://blog.csdn.net/u010928589/article/details/90293703