网络编程-自定义RPC

1.生产者原理:  netty服务端 + 反射
	生产者是netty的服务器,当读取到客户端发送的消息后,获得客户端调用方法的详细数据,根据反射调用生产者中接口实现类的具体方法,并将返回值writeAndFlush到管道中,通过管道响应给客户端
2.消费者原理:  netty客户端 + 反射 + 动态代理
	消费者是netty的客户端,当需要使用到接口时,先获得接口的代理对象,调用接口的方法时,由代理对象作为netty客户端,封装参数,并调用服务端
3.依赖
<dependency>
      <groupId>io.netty</groupId>
      <artifactId>netty-all</artifactId>
      <version>4.1.8.Final</version>
</dependency>
 <dependency>
       <groupId>org.reflections</groupId>
       <artifactId>reflections</artifactId>
       <version>0.9.10</version>
</dependency>
4.找到接口的所有实现类的API
Reflections reflections = new Reflections(packageName);
Set<Class<?>> implSet = (Set<Class<?>>) reflections.getSubTypesOf(interfaceClass);
1.服务器端
public class RPCServer {
    public static void main(String[] args) {
        new RPCServer().run(9999);

    }
    public void run(int port) {
        EventLoopGroup bossGroup = null;
        EventLoopGroup workerGroup = null;
        try {
            //创建netty模型线程池对象
            bossGroup = new NioEventLoopGroup();
            workerGroup = new NioEventLoopGroup();
            //创建启动助手对象
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap //4.设置两个线程组
                    .group(bossGroup, workerGroup)
                    //5.使用NioServerSocketChannel作为服务器端通道的实现
                    .channel(NioServerSocketChannel.class)
                    //6.设置线程队列中等待连接的个数
                    .option(ChannelOption.SO_BACKLOG, 128)
                    //7.保持活动连接状态
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    //8. 创建一个通道初始化对象
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        public void initChannel(SocketChannel socketChannel) {
                            //9. 往PipelineChannel链中添加自定义的handler类
                            socketChannel.pipeline()
                                    //编码解码
                                    .addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)))
                                    .addLast("encoder", new ObjectEncoder())
                                    .addLast(new RPCServerHandler());
                        }
                    });
            ChannelFuture future = serverBootstrap.bind(port).sync();
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}
2.服务器端业务逻辑处理类
public class RPCServerHandler extends ChannelInboundHandlerAdapter {
    private static final String packageName = "com.baidu.rpc.service";
    //读取完成
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //获取消费者发送的封装对象
        ClassInfo classInfo = (ClassInfo) msg;
        //获取生产者调用的接口的类名称
        String className = classInfo.getClassName();
        className = className.substring(className.lastIndexOf("."));
        //拼接当前包,得到生产者对应的接口名
        String interfaceName = packageName + className;
        Class<?> clazz = Class.forName(interfaceName);
        //找到接口的所有实现类集合
        Reflections reflections = new Reflections(packageName);
        Set<Class<?>> implSet = (Set<Class<?>>) reflections.getSubTypesOf(clazz);
        if (implSet == null || implSet.size() == 0) {
            System.out.println("没有匹配上");
        } else if (implSet.size() > 1) {
            System.out.println("匹配不唯一");
        } else {
            //匹配上了唯一的一个
            Class[] classArray = implSet.toArray(new Class[1]);
            //得到了实现类的class对象
            Class implClass = classArray[0];
            Object impl = implClass.newInstance();
            //获取调用的方法
            Method method = implClass.getMethod(classInfo.getMethodName(), classInfo.getMethodTypes());
            //调用方法
            Object result = method.invoke(impl, classInfo.getParams());
            //向管道中输出返回值
            ctx.writeAndFlush(result);
        }
    }
}
3.客户端
public class RPCClient {
    public static Class clazz;

    public static <T> T getProxy(Class<T> cla) {
        clazz = cla;
        return (T) Proxy.newProxyInstance(cla.getClassLoader(), new Class[]{cla}, new MyInvocationHandler());
    }
}

class MyInvocationHandler implements InvocationHandler {
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        EventLoopGroup workerGroup = null;

        RPCClientHandler handler = new RPCClientHandler();
        try {
            //创建线程组对象
            workerGroup = new NioEventLoopGroup();
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(workerGroup)
                    //4. 设置客户端通道的实现类
                    .channel(NioSocketChannel.class)
                    //5. 创建一个通道初始化对象
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) {
                            //6.往Pipeline链中添加自定义的handler
                            socketChannel.pipeline()
                                    //编码解码
                                    .addLast("decoder", new ObjectDecoder(Integer.MAX_VALUE, ClassResolvers.cacheDisabled(null)))
                                    .addLast("encoder", new ObjectEncoder())
                                    .addLast("handler", handler);
                        }
                    });
            //连接服务器
            ChannelFuture future = bootstrap.connect("127.0.0.1", 9999).sync();
            //封装调用的参数
            ClassInfo classInfo = getClassInfo(method, args);
            //发送参数
            Channel channel = future.channel();
            channel.writeAndFlush(classInfo).sync();
            future.channel().closeFuture();
            //等待服务器获得响应结果
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            workerGroup.shutdownGracefully();
        }
        return handler.getResponse();
    }

    //封装客户端发送参数
    private ClassInfo getClassInfo(Method method, Object[] args) {
        ClassInfo classInfo = new ClassInfo();
        //封装类名
        classInfo.setClassName(RPCClient.clazz.getName());
        //获取当前调用的方法
        classInfo.setMethodName(method.getName());
        //封装参数类型
        classInfo.setMethodTypes(method.getParameterTypes());
        //封装实际参数
        classInfo.setParams(args);
        return classInfo;
    }
}
4.客户端业务逻辑处理类
public class RPCClientHandler extends ChannelInboundHandlerAdapter {
    private Object response;
    public Object getResponse() {
        return response;
    }

    public void setResponse(Object response) {
        this.response = response;
    }

    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception 	{
        this.response = msg;
    }
}
5.实体类
public class ClassInfo implements Serializable {
    private String className;   //接口全类名
    private String methodName;     //接口方法名
    private Class[] methodTypes;     //接口参数类型
    private Object[] params;      //参数列表
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值