手写实现RPC 框架

2 篇文章 0 订阅
1 篇文章 0 订阅

1.项目架构

   一个简易的rpc框架,别的先不多说上github

        github

        gitee        

      注册中心 : zookeeper  (使用curator 操作)

      通信框架 : netty  (4.1.25版本)

      序列化 :  kryo  

以下只写了大体项目流程,以及展示部分代码,具体请点击上方github ,代码里基本都写了注释

2. 框架流程

3 . 项目总览

   本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() 方法,导致异常

4. netty构建

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<SocketChannel>() {
                    @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,代码上都有注释

5. 注解模式

这里封装成了对应的 starter 请移步下一篇博文  

https://blog.csdn.net/u010928589/article/details/90293703

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值