美文网首页
第10章 Dubbo 代理层的设计与实现

第10章 Dubbo 代理层的设计与实现

作者: 原水寒 | 来源:发表于2019-07-24 12:55 被阅读0次
    image.png

    本节介绍 Dubbo 十层架构中的 Proxy 层。

    image.png
    • ProxyFactory:代理工厂接口;
    • StubProxyFactoryWrapper:代理工厂装饰类(封装了对 stublocal 的处理逻辑),会在获取 ProxyFactory 具体子类时进行 AOP;
    • AbstractProxyFactory:代理工厂模板类(封装了获取组装接口的功能,用于创建动态代理),提供了模板方法;
    • JavassistProxyFactory:基于 Javassist 实现的代理工厂;
    • JdkProxyFactory:基于 JDK 动态代理实现的代理工厂;
    • AbstractProxyInvoker:最终封装的代理 Invoker,其子类内部发起真正的调用;
    • InvokerInvocationHandler:Proxy 发起调用时,会调用该类的 invoke(...),在该 invoke(...) 方法中,默认会调用 MockClusterInvoker 的 invoke(...),之后一路进行调用。

    一、代理工厂接口 ProxyFactory

    @SPI("javassist")
    public interface ProxyFactory {
        /**
         * 使用端:consumer
         *
         * 创造一个代理,用于服务引用创建代理
         * @param invoker会被proxy调用的第一层Invoker,默认是 MockClusterInvoker
         * @return proxy 代理对象
         */
        @Adaptive({Constants.PROXY_KEY})
        <T> T getProxy(Invoker<T> invoker) throws RpcException;
    
        /**
         * 使用端:provider
         *
         * 创建一个Invoker,默认是代理Invoker -- AbstractProxyInvoker 的子类对象
         * @param <T> 接口 eg. com.alibaba.dubbo.demo.DemoService
         * @param proxy ref实例, eg. emoServiceImpl实例
         * @param type interface eg. com.alibaba.dubbo.demo.DemoService
         * @param url -- 
         *       injvm://127.0.0.1/com.alibaba.dubbo.demo.DemoService?anyhost=true...
         *       registry://127.0.0.1:2181/com.alibaba.dubbo.registry.RegistryService?application=demo-provider...&export=dubbo://10.213.11.98:20880/com.alibaba.dubbo.demo.DemoService?anyhost=true...
         * @return invoker,默认是代理Invoker -- AbstractProxyInvoker 的子类对象
         */
        @Adaptive({Constants.PROXY_KEY})
        <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException;
    }
    

    二、代理工厂装饰类 StubProxyFactoryWrapper

    public class StubProxyFactoryWrapper implements ProxyFactory {
        // 真正的ProxyFactory具体子类(JavassistProxyFactory/JdkProxyFactory)
        private final ProxyFactory proxyFactory;
        
        // 具有父类SPI接口(ProxyFactory)的单参构造器,所以该类是一个Wrapper类,会在getExtension获取ProxyFactory具体子类时进行aop
        public StubProxyFactoryWrapper(ProxyFactory proxyFactory) {
            this.proxyFactory = proxyFactory;
        }
    
        /**
         * 使用端:consumer
         */
        @Override
        public <T> T getProxy(Invoker<T> invoker) throws RpcException {
            // 1. 调用 ProxyFactory 获取代理
            T proxy = proxyFactory.getProxy(invoker);
            // 2. 如果不是泛化接口,处理 stub 和 local
            ...
            return proxy;
        }
    
        /**
         * 使用端:provider
         */
        @Override
        public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) throws RpcException {
            return proxyFactory.getInvoker(proxy, type, url);
        }
    }
    

    三、代理工厂模板类 AbstractProxyFactory

    public abstract class AbstractProxyFactory implements ProxyFactory {
        @Override
        public <T> T getProxy(Invoker<T> invoker) throws RpcException {
            /**
             * 1. 构造接口参数,默认只有 invoker.getInterface()(eg. DemoService), EchoService.class 两个接口
             */
            ...
            Class<?>[] interfaces = new Class<?>[]{invoker.getInterface(), EchoService.class};
            ...
    
            /**
             * 2. 调用子类的实现去创建代理
             */
            return getProxy(invoker, interfaces);
        }
    
        /**
         * 提供给子类的抽象方法
         */
        public abstract <T> T getProxy(Invoker<T> invoker, Class<?>[] types);
    
    }
    

    四、JdkProxyFactory

    public class JdkProxyFactory extends AbstractProxyFactory {
        // 使用端:consumer
        @Override
        public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
            // 使用JDK方式创建Java动态代理,创建了动态代理的逻辑处理类 InvokerInvocationHandler,并且传入了 MockClusterInvoker
            return (T) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(), interfaces, new InvokerInvocationHandler(invoker));
        }
    
        // 使用端:provider
        @Override
        public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
            // 创建真正的Invoker代理
            return new AbstractProxyInvoker<T>(proxy, type, url) {
                @Override
                protected Object doInvoke(T proxy, String methodName,
                                          Class<?>[] parameterTypes,
                                          Object[] arguments) throws Throwable {
                    // 获取真正的方法Method,proxy=DemoServiceImpl实例
                    Method method = proxy.getClass().getMethod(methodName, parameterTypes);
                    // 执行真正的方法
                    return method.invoke(proxy, arguments);
                }
            };
        }
    }
    

    五、JavassistProxyFactory

    public class JavassistProxyFactory extends AbstractProxyFactory {
        // 使用端:consumer
        @Override
        public <T> T getProxy(Invoker<T> invoker, Class<?>[] interfaces) {
            // 使用 com.alibaba.dubbo.common.bytecode.Proxy 创建代理,创建了动态代理的逻辑处理类 InvokerInvocationHandler,并且传入了 MockClusterInvoker
            return (T) Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
        }
    
        // 使用端:provider
        @Override
        public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
            // wrapper:通过动态生成一个真实的服务提供者(DemoServiceImpl)的wrapper类,来避免反射调用
            final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass());
            return new AbstractProxyInvoker<T>(proxy, type, url) {
                @Override
                protected Object doInvoke(T proxy, String methodName,
                                          Class<?>[] parameterTypes,
                                          Object[] arguments) throws Throwable {
                    // 直接调用wrapper,wrapper底层调用DemoServiceImpl
                    return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
                }
            };
        }
    }
    

    首先来看下 consumer 端:

    Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker))
    

    这里首先调用 Proxy.getProxy(interfaces) 获取到一个创建代理的工厂类 com.alibaba.dubbo.common.bytecode.Proxy0,如下:

    package com.alibaba.dubbo.common.bytecode;
    
    import com.alibaba.dubbo.common.bytecode.ClassGenerator;
    import com.alibaba.dubbo.common.bytecode.Proxy;
    import com.alibaba.dubbo.common.bytecode.proxy0;
    import java.lang.reflect.InvocationHandler;
    
    public class Proxy0 extends Proxy implements ClassGenerator.DC {
        public Object newInstance(InvocationHandler invocationHandler) {
            return new proxy0(invocationHandler);
        }
    }
    

    之后调用了 Proxy0#newInstance 方法,创建了一个 com.alibaba.dubbo.common.bytecode.proxy0 实例,该实例就是最终的 DemoService 的代理对象。

    DemoService demoService = (DemoService) context.getBean("demoService");
    

    这里的 demoService 就是上述的 com.alibaba.dubbo.common.bytecode.proxy0 实例。

    package com.alibaba.dubbo.common.bytecode;
    
    import com.alibaba.dubbo.common.bytecode.ClassGenerator;
    import com.alibaba.dubbo.demo.DemoService;
    import com.alibaba.dubbo.rpc.service.EchoService;
    import java.lang.reflect.InvocationHandler;
    import java.lang.reflect.Method;
    
    public class proxy0 implements EchoService, DemoService {
        public static Method[] methods;
        private InvocationHandler handler;
    
        public String sayHello(String string) {
            Object[] arrobject = new Object[]{string};
            Object object = this.handler.invoke(this, methods[0], arrobject);
            return (String)object;
        }
    
        public Object $echo(Object object) {
            Object[] arrobject = new Object[]{object};
            Object object2 = this.handler.invoke(this, methods[1], arrobject);
            return object2;
        }
    
        public proxy0() {
        }
    
        public proxy0(InvocationHandler invocationHandler) {
            this.handler = invocationHandler;
        }
    }
    
    • proxy0 实现的接口就是 AbstractProxyFactory 中获取的接口;
    • 当调用 proxy0#sayHello 时,实际上其内部执行的是 InvokerInvocationHandlerr#invoke,来看一下 InvokerInvocationHandler。

    六、代理逻辑处理类 InvokerInvocationHandler

    public class InvokerInvocationHandler implements InvocationHandler {
        /**
         * 第一个被Proxy调用的Invoker,默认为MockClusterInvoker
         */
        private final Invoker<?> invoker;
    
        public InvokerInvocationHandler(Invoker<?> handler) {
            this.invoker = handler;
        }
    
        @Override
        public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
            ...
            // 1. 创建请求参数RpcInvocation
            // 2. 执行调用
            // 3. 对调用结果进行重建recreate():若响应有异常,直接抛异常;否则返回响应
            return invoker.invoke(new RpcInvocation(method, args)).recreate();
        }
    }
    

    七、Invoker代理 AbstractProxyInvoker

    public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
        // 真实对象 ref, eg. DemoServiceImpl
        private final T proxy;
        // 接口类型,eg. DemoService
        private final Class<T> type;
        ...
        public AbstractProxyInvoker(T proxy, Class<T> type, URL url) {
            ...
            this.proxy = proxy;
            this.type = type;
            ...
        }
       ...
        /**
         * 进行调用
         * @param invocation 请求参数
         * @return 返回结果
         * @throws RpcException
         */
        @Override
        public Result invoke(Invocation invocation) throws RpcException {
            try {
                // 1. 调用子类发起请求
                // 2. 包装响应为 RpcResult
                return new RpcResult(doInvoke(proxy, invocation.getMethodName(), invocation.getParameterTypes(), invocation.getArguments()));
            } catch (InvocationTargetException e) {
                return new RpcResult(e.getTargetException());
            } catch (Throwable e) {
                throw new RpcException("Failed to invoke remote proxy method " + invocation.getMethodName() + " to " + getUrl() + ", cause: " + e.getMessage(), e);
            }
        }
    
        // 子类覆写的真正调用的方法
        protected abstract Object doInvoke(T proxy, String methodName, Class<?>[] parameterTypes, Object[] arguments) throws Throwable;
    }
    

    AbstractProxyInvoker 的子类在 JdkProxyFactory#getInvoker(...)JavassistProxyFactory#getInvoker(...) 中进行创建的,来看下JavassistProxyFactory#getInvoker(...)

        // 使用端:provider
        @Override
        public <T> Invoker<T> getInvoker(T proxy, Class<T> type, URL url) {
            // wrapper:通过动态生成一个真实的服务提供者(DemoServiceImpl)的wrapper类,来避免反射调用
            final Wrapper wrapper = Wrapper.getWrapper(proxy.getClass());
            return new AbstractProxyInvoker<T>(proxy, type, url) {
                @Override
                protected Object doInvoke(T proxy, String methodName,
                                          Class<?>[] parameterTypes,
                                          Object[] arguments) throws Throwable {
                    // 直接调用wrapper,wrapper底层调用DemoServiceImpl
                    return wrapper.invokeMethod(proxy, methodName, parameterTypes, arguments);
                }
            };
        }
    

    再贴下最终生成的 wrapper 类实例(com.alibaba.dubbo.common.bytecode.Wrapper0)。

    package com.alibaba.dubbo.common.bytecode;
    
    import com.alibaba.dubbo.common.bytecode.ClassGenerator;
    import com.alibaba.dubbo.common.bytecode.NoSuchMethodException;
    import com.alibaba.dubbo.common.bytecode.NoSuchPropertyException;
    import com.alibaba.dubbo.common.bytecode.Wrapper;
    import com.alibaba.dubbo.demo.DemoService;
    import java.lang.reflect.InvocationTargetException;
    import java.util.Map;
    
    public class Wrapper0 extends Wrapper implements ClassGenerator.DC {
        ...
        /**
         * @param object 实现类ref,eg. DemoServiceImpl
         * @param string 方法名称
         * @param arrclass 参数类型
         * @param arrobject 参数值
         * @return 调用返回值
         * @throws java.lang.reflect.InvocationTargetException
         */
        public Object invokeMethod(Object object, String string, Class[] arrclass, Object[] arrobject) throws InvocationTargetException {
            DemoService demoService;
            try {
                demoService = (DemoService)object;
            } catch (Throwable throwable) {
                throw new IllegalArgumentException(throwable);
            }
            try {
                if ("sayHello".equals(string) && arrclass.length == 1) {
                    return demoService.sayHello((String)arrobject[0]);
                }
            } catch (Throwable throwable) {
                throw new InvocationTargetException(throwable);
            }
            throw new NoSuchMethodException(new StringBuffer().append("Not found method \"").append(string).append("\" in class com.alibaba.dubbo.demo.DemoService.").toString());
        }
        ...
    }
    

    相关文章

      网友评论

          本文标题:第10章 Dubbo 代理层的设计与实现

          本文链接:https://www.haomeiwen.com/subject/ghgilctx.html