netty 实现rpc框架


netty 实现rpc框架

         

                 

                                   

基本介绍

          

                           

                

annotation:自定义注解标识接口实现类

protocol:自定义注册协议、消费协议

registry:注册中心,注册服务元数据

provider:生产端,向注册中心注册服务,提供接口实现类

conusmer:消费端,从注册中心拉取元数据,并向provider发起服务调用

         

Registry:自定义注解,标识接口实现类

@Documented
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Registry {
}

             

RegistryInfo:服务注册元数据

@Data
public class RegistryInfo implements Serializable {

    private List<RegistryProtocol> registryProtocols;
}

         

RpcResult:远程服务调用结果

@Data
public class RpcResult implements Serializable {

    private boolean hasError;
    private String errorMessage;
    private Object value;
}

            

Person

@Data
public class Person implements Serializable {

    private String name;
    private Integer age;
}

         

               

                                   

自定义协议

      

RegistryProtocol:服务注册协议

@Data
public class RegistryProtocol implements Serializable {

    private String interfaceName;
    private String implClassName;
    private Integer providerPort;
}

         

ConsumerProtocol:消费协议

@Data
public class ConsumerProtocol implements Serializable {

    private String interfaceName;
    private String implClassName;
    private String methodName;
    private Class<?>[] params;
    private Object[] values;
}

         

              

                                   

注册中心

    

RegistryVariables:存储接口对应的元数据

public class RegistryVariables {

    public static final Map<String, RegistryProtocol> interfaceProviderPortMap = new HashMap<>();

    public static RegistryProtocol getInterfaceProviderPortMap(String interfaceName) {
        return interfaceProviderPortMap.get(interfaceName);
    }
}

         

CustomRegistryProviderHandler:处理服务端服务注册

public class CustomRegistryProviderHandler extends SimpleChannelInboundHandler<List<RegistryProtocol>> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, List<RegistryProtocol> registryProtocols) throws Exception {
        if (registryProtocols.size() != 0){
            registryProtocols.forEach(item -> RegistryVariables.interfaceProviderPortMap.put(item.getInterfaceName(), item));
        }
    }
}

            

CustomRegistryConsumerHandler:处理消费端服务元数据拉取

public class CustomRegistryConsumerHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
        if ("fetch registry infos".equalsIgnoreCase(s)){
            RegistryInfo registryInfo = new RegistryInfo();
            registryInfo.setRegistryProtocols(new ArrayList<>(RegistryVariables.interfaceProviderPortMap.values()));
            channelHandlerContext.channel().writeAndFlush(registryInfo);
        }
    }
}

         

RegistryServer:注册中心服务器

public class RegistryServer {

    public static void startServer(int port){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline channelPipeline = socketChannel.pipeline();
                            channelPipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
                            channelPipeline.addLast(new LengthFieldPrepender(4));
                            channelPipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(RegistryServer.class.getClassLoader())));
                            channelPipeline.addLast(new ObjectEncoder());
                            channelPipeline.addLast(new CustomRegistryProviderHandler());
                            channelPipeline.addLast(new CustomRegistryConsumerHandler());
                        }
                    });

            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        startServer(8000);
    }
}

       

               

                                   

服务端

   

HelloService

public interface HelloService {

    Person hello(String name, Integer age);
}

          

HelloService2

public interface HelloService2 {

    String hello();
}

           

HelloServiceImpl

@Registry
public class HelloServiceImpl implements HelloService{

    @Override
    public Person hello(String name, Integer age) {
        Person person = new Person();
        person.setName(name);
        person.setAge(age);

        return person;
    }
}

         

HelloService2Impl

@Registry
public class HelloService2Impl implements HelloService2{

    @Override
    public String hello() {
        return "瓜田李下";
    }
}

             

ProviderVariables:存储接口、实现类实例

public class ProviderVariables {

    public static final Integer providerServerPort = 8001;
    public static Map<String, Object> instanceMap = new HashMap<>();

    public static Map<String, Object> getInstanceMap() {
        return instanceMap;
    }

    public static void putInstance(String interfaceName, Object instance){
        instanceMap.put(interfaceName, instance);
    }
}

        

CustomProviderRegistryHandler:向注册中心注册服务

public class CustomProviderRegistryHandler extends ChannelInboundHandlerAdapter {

    private final static Set<String> existInterfaceNames = new HashSet<>();
    private final Integer providerServerPort;

    public CustomProviderRegistryHandler(Integer providerServerPort){
        this.providerServerPort = providerServerPort;
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.executor().scheduleAtFixedRate(()->{
            Set<String> newInterfaceClassNames = new HashSet<>();
            doScan("com.example.demo.rpc.provider.service", newInterfaceClassNames);

            if (newInterfaceClassNames.size() != 0){
                List<RegistryProtocol> registryProtocols = new ArrayList<>();

                for (String item : newInterfaceClassNames){
                    RegistryProtocol registryProtocol = new RegistryProtocol();

                    try {
                        Class<?> implClass = Class.forName(item);
                        registryProtocol.setInterfaceName((implClass.getInterfaces()[0]).getName());
                        registryProtocol.setProviderPort(providerServerPort);
                        registryProtocol.setImplClassName(item);

                        registryProtocols.add(registryProtocol);
                    }catch (Exception e){
                        e.printStackTrace();
                    }
                }

                ctx.channel().writeAndFlush(registryProtocols);
            }
        },0,10, TimeUnit.SECONDS);
    }

    private void doScan(String path, Set<String> newInterfaceClassNames){
        File file = new File(ProviderRegistryClient.class.getClassLoader().getResource(path.replaceAll("\\.","/")).getPath());
        for (File item : Objects.requireNonNull(file.listFiles())){
            if (item.isDirectory()){
                doScan(path+item.getName(), newInterfaceClassNames);
            }else {
                String fileName = path+"."+item.getName();
                String className = fileName.substring(0,fileName.indexOf(".class"));

                try {
                    Class<?> providerClass = Class.forName(className);
                    if (providerClass.isAnnotationPresent(Registry.class)){
                        if (!existInterfaceNames.contains(className)){
                            newInterfaceClassNames.add(className);
                            existInterfaceNames.add(className);
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }
            }
        }
    }
}

            

CustomProviderConsumerHandler:处理消费端的远程调用

public class CustomProviderConsumerHandler extends SimpleChannelInboundHandler<ConsumerProtocol> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, ConsumerProtocol consumerProtocol) throws Exception {
        System.out.println("收到客户端请求信息:"+consumerProtocol);

        RpcResult result = new RpcResult();

        String interfaceName = consumerProtocol.getInterfaceName();
        String implClassName = consumerProtocol.getImplClassName();
        Class<?>[] params = consumerProtocol.getParams();
        Object[] values = consumerProtocol.getValues();

        Object instance = null;
        System.out.println(ProviderVariables.getInstanceMap());
        if (ProviderVariables.getInstanceMap().containsKey(interfaceName)){
            instance = ProviderVariables.getInstanceMap().get(interfaceName);
        }else {
            try {
                instance = Class.forName(implClassName).newInstance();
                ProviderVariables.getInstanceMap().put(interfaceName,instance);
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        if (instance != null){
            Method method = instance.getClass().getMethod(consumerProtocol.getMethodName(), params);

            try {
                result.setValue(method.invoke(instance, values));
            }catch (Exception e){
                result.setHasError(true);
                result.setErrorMessage(e.getMessage());
            }
        }

        System.out.println(result);
        channelHandlerContext.channel().writeAndFlush(result);
    }
}

          

ProviderRegistryClient:服务注册客户端

public class ProviderRegistryClient {

    public static void provide(String host, int port){
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline channelPipeline = socketChannel.pipeline();
                            channelPipeline.addLast(new LengthFieldPrepender(4));
                            channelPipeline.addLast(new ObjectEncoder());
                            channelPipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(this.getClass().getClassLoader())));
                            channelPipeline.addLast(new CustomProviderRegistryHandler(ProviderVariables.providerServerPort));
                        }
                    });
            ChannelFuture channelFuture = bootstrap.connect(host,port).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            eventLoopGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        String host = "localhost";
        int port = 8000;
        provide(host, port);
    }
}

         

ProviderConsumerServer:服务端处理消费端请求的服务器

public class ProviderConsumerServer {

    public static void startServer(int port){
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)
                    .option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true)
                    .childHandler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline channelPipeline = socketChannel.pipeline();
                            channelPipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0,4,0,4));
                            channelPipeline.addLast(new LengthFieldPrepender(4));
                            channelPipeline.addLast(new ObjectEncoder());
                            channelPipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(ProviderConsumerServer.class.getClassLoader())));
                            channelPipeline.addLast(new CustomProviderConsumerHandler());
                        }
                    });

            ChannelFuture channelFuture = serverBootstrap.bind(port).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

    public static void main(String[] args) {
        startServer(ProviderVariables.providerServerPort);
    }
}

         

              

                                   

消费端

   

ConsumerVariables:存储注册中心拉取的元数据

public class ConsumerVariables {

    public static final Set<RegistryProtocol> registryProtocolSet = new HashSet<>();

    public static void addRegistryProtocols(Collection<RegistryProtocol> registryProtocols){
        registryProtocolSet.addAll(registryProtocols);
    }

    public static Set<RegistryProtocol> getRegistryProtocolSet(){
        return registryProtocolSet;
    }
}

        

RpcProxy:创建代理服务

public class RpcProxy {

    @SuppressWarnings("all")
    public static <T> T createProxy(Class<?> clz){
        return (T)Proxy.newProxyInstance(RpcProxy.class.getClassLoader(),
                new Class[]{clz},new InterfaceProxy(clz));
    }
}

         

InterfaceProxy:拉取元数据、执行远程调用

public class InterfaceProxy implements InvocationHandler {

    private final Class<?> clz;

    public InterfaceProxy(Class<?> clz) {
        this.clz = clz;
    }

    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        boolean fetch = true;
        for (RegistryProtocol protocol : ConsumerVariables.getRegistryProtocolSet()){
            if (protocol.getInterfaceName().equalsIgnoreCase(clz.getName())) {
                fetch = false;
                break;
            }
        }

        if (fetch){
            System.out.println("开始拉取注册信息");
            fetchInfos();
            System.out.println(ConsumerVariables.getRegistryProtocolSet());
        }

        RpcResult result = getResult(method, args);
        if (result.isHasError()){
            throw new RuntimeException(result.getErrorMessage());
        }

        return result.getValue();
    }

    private void fetchInfos(){
        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline channelPipeline = socketChannel.pipeline();
                            channelPipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
                            channelPipeline.addLast(new LengthFieldPrepender(4));
                            channelPipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(InterfaceProxy.class.getClassLoader())));
                            channelPipeline.addLast(new ObjectEncoder());
                            channelPipeline.addLast(new CustomConsumerInfosHandler());
                        }
                    });

            ChannelFuture channelFuture = bootstrap.connect("localhost",8000).sync();
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            eventLoopGroup.shutdownGracefully();
        }
    }

    private RpcResult getResult(Method method, Object[] args){
        int port=0;

        ConsumerProtocol protocol = new ConsumerProtocol();
        protocol.setInterfaceName(clz.getName());
        protocol.setMethodName(method.getName());
        protocol.setParams(method.getParameterTypes());
        protocol.setValues(args);
        for (RegistryProtocol item : ConsumerVariables.getRegistryProtocolSet()){
            if (item.getInterfaceName().equalsIgnoreCase(clz.getName())){
                System.out.println(item);
                port = item.getProviderPort();
                protocol.setImplClassName(item.getImplClassName());
            }
        }

        EventLoopGroup eventLoopGroup = new NioEventLoopGroup();

        CustomConsumerResultHandler customConsumerResultHandler = new CustomConsumerResultHandler();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(eventLoopGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline channelPipeline = socketChannel.pipeline();
                            channelPipeline.addLast(new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE,0,4,0,4));
                            channelPipeline.addLast(new LengthFieldPrepender(4));
                            channelPipeline.addLast(new ObjectDecoder(ClassResolvers.cacheDisabled(InterfaceProxy.class.getClassLoader())));
                            channelPipeline.addLast(new ObjectEncoder());
                            channelPipeline.addLast(customConsumerResultHandler);
                        }
                    });
            ChannelFuture channelFuture = bootstrap.connect("localhost",port).sync();
            channelFuture.channel().writeAndFlush(protocol);
            channelFuture.channel().closeFuture().sync();
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            eventLoopGroup.shutdownGracefully();
        }

        return customConsumerResultHandler.getResult();
    }
}

           

CustomConsumerInfosHandler:拉取元数据

public class CustomConsumerInfosHandler extends SimpleChannelInboundHandler<RegistryInfo> {

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        ctx.channel().writeAndFlush("fetch registry infos");
    }

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RegistryInfo registryInfo) throws Exception {
        ConsumerVariables.addRegistryProtocols(registryInfo.getRegistryProtocols());
        channelHandlerContext.channel().close();
    }
}

            

CustomConsumerResultHandler:执行远程调用

public class CustomConsumerResultHandler extends SimpleChannelInboundHandler<RpcResult> {

    private RpcResult result;

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, RpcResult rpcResult) throws Exception {
        System.out.println("rpcResult:"+rpcResult);
        result = rpcResult;
        channelHandlerContext.channel().close();
    }

    public RpcResult getResult(){
        return result;
    }
}

               

Test:消费端发起远程调用

public class Test {

    public static void main(String[] args) {
        HelloService helloService = RpcProxy.createProxy(HelloService.class);
        System.out.println(helloService.hello("瓜田李下",20));

        HelloService2 helloService2 = RpcProxy.createProxy(HelloService2.class);
        System.out.println(helloService2.hello());
    }
}

         

              

                                   

使用测试

  

依次启动注册中心、服务端、消费端,test控制台输出:

# helloService.hello("瓜田李下",20)
RpcResult(hasError=false, errorMessage=null, value=Person(name=瓜田李下, age=20))
Person(name=瓜田李下, age=20)

# helloService2.hello()
rpcResult:RpcResult(hasError=false, errorMessage=null, value=瓜田李下)
RpcResult(hasError=false, errorMessage=null, value=瓜田李下)
瓜田李下

        

                

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值