• Dubbo泛化调用入门到精通


    Dubbo 泛化调用、阿里的好舒服的泛化调用都是类似的功能。最近给同事排查一个dubbo-admin 控制台调用报错的问题的小研究,为此还给社区提了一个issue,具体可以查看链接 dubbo-admin 泛型参数测试 ClassNotFoundException 看了最新版本好像自动去掉了出现泛型<这样的信息通通干掉,不过没有发布release版本。 参考文档:使用泛化调用


    1、泛化调用

    1.1 概念

    泛化接口调用方式主要用于客户端没有 API 接口(泛化调用是指不需要依赖服务的二方包)及模型类元的情况,参数及返回值中的所有 POJO 均用 Map 表示,通常用于框架集成,API网关比如:实现一个通用的服务测试框架,可通过 GenericService 调用所有服务实现。泛化调用的方式可以有效减少平台型产品的二方包依赖,实现系统的轻量级运行。对于服务提供方新增的接口不需要修改二方包的版本,即可调用,不方便的就是对于数据入参、返回值由于没有二方包很难理解,全部都是org.apache.dubbo.common.utils.PojoUtils#generalize(java.lang.Object) 转换为基本类型或者Map等等。

    特点
    • 没有二方、三方的 接口的类信息、class 字节码
    • 直接通过基本的类型参数表示复杂的对象

    1.2 PojoUtils 说明

    PojoUtils. Travel object deeply, and convert complex type to simple type. (深度遍历对象,并将复杂类型转换为简单类型),同时也提供了反向转换。
    Simple type below will be remained:

    • Primitive Type, also include String, Number(Integer, Long), Date
    • Array of Primitive Type
    • Collection, eg: List, Map, Set etc.
    • Other type will be covert to a map which contains the attributes and value pair of object.

    PojoUtils 提供了讲复杂对象转换为简单的对象,通过简单对象转换为复杂对象。有点像序列化和反序列话,你要说它是不是,感觉也没错哈!官方的测试例子不错,可以去了解一下

     List users = new ArrayList<>();
     User user = new User();
     user.setName("other");
     user.setAge(31);
     users.add(user);
    
     Object generalize = PojoUtils.generalize(users);
     System.out.println(generalize);
     
     //[{name=other, class=org.apache.dubbo.samples.Dto.User, age=31}]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    2、泛化例子

    基于官方demo 中 dubbo-samples-zookeper,本地安装一个zk 即可启动
    https://github.com/apache/dubbo-samples/tree/master/java/dubbo-samples-zookeeper

    2.1 实践指南

    泛化调用最好的一个参考例子就是dubbo-admin 中 ,通过泛化进行控制台的调用实践,泛化没有二方包,服务提供方的方法参数类型无法直接使用强类型表示,传递的参数也无法直接使用强类型只能通过 参考 :PojoUtils 序列化 Object generalize = PojoUtils.generalize(data) 例子传递 Map、List 、Array 等基本类型的参数
    eg List -> [{name=other, age=31, class=org.apache.dubbo.samples.Dto.User}] 就是List 这样的结构**,中增加 class 字段信息,反序列化时候使用表征对应的泛型的信息,或者类class的信息**。

    泛化必须参数
    • 服务的名称、版本、分组 唯一限定符
    • 方法名称、方法泛型参数类型
    • 传递的 PojoUtils.generalize(data) 序列化后的基本参数

    为啥需要这些,就是为了找到具体的接口的提供者、接口的具体的方法是哪个?调用传递的参数是啥,即可享受正常的调用逻辑。如下是dubbo-admin 控制台实践指南,Dubbo API 网关也是类似的概念哦!只要通过配置或者传递参数中有如下的概念即可搞定问题。

    泛化泛化的结果:也是基本类型的数据,根据 PojoUtils.generalize(result) 根据result 进行Pojo作为泛化的结果。如下是 dubbo-admin 控制台测试的代码
    https://github.com/apache/dubbo-admin/blob/develop/dubbo-admin-server/src/main/java/org/apache/dubbo/admin/service/impl/GenericServiceImpl.java

    public Object invoke(String service, String method, String[] parameterTypes, Object[] params) {
    
            ReferenceConfig reference = new ReferenceConfig<>();
            String group = Tool.getGroup(service);
            String version = Tool.getVersion(service);
            String intf = Tool.getInterface(service);
            reference.setGeneric(true);
            reference.setApplication(applicationConfig);
            reference.setInterface(intf);
            reference.setVersion(version);
            reference.setGroup(group);
    
            try {
                removeGenericSymbol(parameterTypes);
                GenericService genericService = reference.get();
                return genericService.$invoke(method, parameterTypes, params);
            } finally {
                reference.destroy();
            }
        }
    
        /**
         * remove generic from parameterTypes 排除掉泛型信息
         *
         * @param parameterTypes
         */
        private void removeGenericSymbol(String[] parameterTypes){
            for (int i = 0; i < parameterTypes.length; i++) {
                int index = parameterTypes[i].indexOf("<");
                if (index > -1) {
                    parameterTypes[i] = parameterTypes[i].substring(0, index);
                }
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    2.2 简单的泛化调用

    Provider 接口

    针对官方的版本 添加了一个泛化的对象的接口

    import java.util.List;
    
    import org.apache.dubbo.config.annotation.Service;
    import org.apache.dubbo.samples.Dto.User;
    import org.apache.dubbo.samples.api.GreetingService;
    
    @Service(version = "1.0.0.daily", group = "dubbo")
    public class AnnotatedGreetingService implements GreetingService {
    
        /**
         * 简单测试
         * 
         * @param name
         * @return
         */
        @Override
        public String sayHello(String name) {
            System.out.println("greeting service received: " + name);
            return "hello, " + name;
        }
    
        /**
         * 测试泛型接口
         * 
         * @param users
         * @return
         */
        @Override
        public List getListUserIncludeMe(List users) {
            if (users == null) {
                return null;
            }
            User user = new User();
            user.setName("wangji");
            user.setAge(28);
            users.add(user);
            return users;
        }
    }
    
    
    /**
     * @author wangji
     * @date 2020/6/2 7:12 PM
     */
    public class User {
        private String name;
    
        private Integer age;
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    
        public Integer getAge() {
            return age;
        }
    
        public void setAge(Integer age) {
            this.age = age;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    泛化调用

    最最关键的地方在于 genericService.$invoke,调用这个泛化接口的几个最主要的参数信息。最好自己动手实践一下子。

    public static void main(String[] args) {
    
        ApplicationConfig application = new ApplicationConfig();
        application.setName("Test-" + UUID.randomUUID().toString());
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");
        application.setRegistry(registryConfig);
        application.setQosEnable(false);
    
        ReferenceConfig reference = new ReferenceConfig<>();
        String group = "dubbo";
        String version = "1.0.0.daily";
        String interfaceName = "org.apache.dubbo.samples.api.GreetingService";
        reference.setGeneric(true);
        reference.setApplication(application);
        reference.setInterface(interfaceName);
        reference.setVersion(version);
        reference.setGroup(group);
        GenericService genericService = reference.get();
    
        Object data = genericService.$invoke("sayHello", new String[] { "java.lang.String" },
                                             new Object[] { "wangji" });
    
        System.out.println("result:" + data);
    
     }
    // result:hello, wangji
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    2.3 含有泛型对象的泛化调用

    如果你不知道怎么编写这个参数,可以 PojoUtils.generalize(data) 通过这个接口来生成对象,来看一下生成的数据的结构是咋样的。

    注意泛型参数传递的参数类型不包含 java.util.List 后面的泛型的信息,只需要传递 java.util.List 即可。

     public static void main(String[] args) {
    
         ApplicationConfig application = new ApplicationConfig();
         application.setName("Test-" + UUID.randomUUID().toString());
         RegistryConfig registryConfig = new RegistryConfig();
         registryConfig.setAddress("zookeeper://127.0.0.1:2181");
         application.setRegistry(registryConfig);
         application.setQosEnable(false);
    
         ReferenceConfig reference = new ReferenceConfig<>();
         String group = "dubbo";
         String version = "1.0.0.daily";
         String interfaceName = "org.apache.dubbo.samples.api.GreetingService";
         reference.setGeneric(true);
         reference.setApplication(application);
         reference.setInterface(interfaceName);
         reference.setVersion(version);
         reference.setGroup(group);
         GenericService genericService = reference.get();
    
         List users = new ArrayList<>();
         User user = new User();
         user.setName("other");
         user.setAge(31);
         users.add(user);
    
         Object generalize = PojoUtils.generalize(users);
         System.out.println(generalize);
    
         Object getListUserIncludeMe = genericService.$invoke("getListUserIncludeMe", new String[] { "java.util.List" },
                                                              new Object[] { generalize });
    
         System.out.println(getListUserIncludeMe);
    
        }
    
    // [{name=other, class=org.apache.dubbo.samples.Dto.User, age=31}]
    // [{name=other, class=org.apache.dubbo.samples.Dto.User, age=31}, {name=wangji, class=org.apache.dubbo.samples.Dto.User, age=28}]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2.4 指定IP调用Provider

    测试环境中相同的服务会存在多台,如果你想调用具体的某台机子咋办呢?指定具体的IP进行调用,没有看到官方的文档、问了一下小杰子的实践,参考试了一下泛化调用直接ip 也是ok的,只需要找到具体的服务提供者即可。
    不过不同的版本好像不一样,没有仔细尝试

    设置服务的url 即可满足,能够定位一个服务即可

    dubbo 版本 2.7.2
    reference.setUrl("dubbo://192.168.1.3:20880/org.apache.dubbo.samples.api.GreetingService");
    
    • 1
    dubbo 版本 2.7.0

    需要添加分组的信息才行

    reference.setUrl("dubbo://192.168.1.3:20880/分组/org.apache.dubbo.samples.api.GreetingService");
    
    • 1
    指定ip调用完整的例子

    基于 2.7.2 版本

    public static void main(String[] args) {
        ApplicationConfig application = new ApplicationConfig();
        application.setName("Test-" + UUID.randomUUID().toString());
        RegistryConfig registryConfig = new RegistryConfig();
        registryConfig.setAddress("zookeeper://127.0.0.1:2181");
        application.setRegistry(registryConfig);
        application.setQosEnable(false);
    
        ReferenceConfig reference = new ReferenceConfig<>();
        String group = "dubbo";
        String version = "1.0.0.daily";
        String interfaceName = "org.apache.dubbo.samples.api.GreetingService";
        reference.setGeneric(true);
        reference.setApplication(application);
        reference.setInterface(interfaceName);
        reference.setVersion(version);
        reference.setGroup(group);
    
        reference.setUrl("dubbo://192.168.1.3:20880/org.apache.dubbo.samples.api.GreetingService");
        GenericService genericService = reference.get();
    
        Object data = genericService.$invoke("sayHello", new String[] { "java.lang.String" },
                                             new Object[] { "wangji" });
    
        System.out.println("result:" + data);
    
     }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    issue 中错误的调用

    java.util.List 这个是由于PojoUtils的实现问题,导致这样的写法是有问题的。

    Object getListUserIncludeMe = genericService.$invoke("getListUserIncludeMe", new String[] { "java.util.List" },
                                                                 new Object[] { generalize });
        
    // at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
    // at org.apache.dubbo.rpc.filter.EchoFilter.invoke(EchoFilter.java:41)
    // at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$1.invoke(ProtocolFilterWrapper.java:82)
    // at org.apache.dubbo.rpc.protocol.ProtocolFilterWrapper$CallbackRegistrationInvoker.invoke(ProtocolFilterWrapper.java:150)
    // at org.apache.dubbo.rpc.protocol.dubbo.DubboProtocol$1.reply(DubboProtocol.java:152)
    // at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.handleRequest(HeaderExchangeHandler.java:102)
    // at org.apache.dubbo.remoting.exchange.support.header.HeaderExchangeHandler.received(HeaderExchangeHandler.java:193)
    // at org.apache.dubbo.remoting.transport.DecodeHandler.received(DecodeHandler.java:51)
    // at org.apache.dubbo.remoting.transport.dispatcher.ChannelEventRunnable.run(ChannelEventRunnable.java:57)
    // at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
    // at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
    // at java.lang.Thread.run(Thread.java:748)
    // Caused by: java.lang.ClassNotFoundException: java.util.List
    // at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    // at java.lang.ClassLoader.loadClass(ClassLoader.java:424)
    // at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:349)
    // at java.lang.ClassLoader.loadClass(ClassLoader.java:357)
    // at java.lang.Class.forName0(Native Method)
    // at java.lang.Class.forName(Class.java:348)
    // at org.apache.dubbo.common.utils.ReflectUtils.name2class(ReflectUtils.java:743)
    // at org.apache.dubbo.common.utils.ReflectUtils.name2class(ReflectUtils.java:670)
    // at org.apache.dubbo.common.utils.ReflectUtils.findMethodByMethodSignature(ReflectUtils.java:885)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    3、实现原理

    dubbo泛化调用原理 画的这个图不错十分的形象生动,可以总结一下 泛化的原理

    原理简介

    +-------------------------------------------+               +-------------------------------------------+
    |  consumer 端                               |               | provider 端                                |
    |                                           |               |                                           |
    |                                           |               |                                           |
    |                                           |               |                                           |
    |                                           |               |                                           |
    |                    +------------------+   |               |       +--------------+                    |
    |                    |GenericImplFilter |   |  Invocation   |       |GenericFilter |                    |
    |             +----> |                  +-------------------------> |              |                    |
    |             |      +------------------+   |               |       +--------------+                    |
    | +-----------+                             |               |                      |    +-----------+   |
    | |           |                             |               |                      |    |           |   |
    | |Client     |                             |               |                      +--> | Service   |   |
    | |           |                             |               |                           |           |   |
    | +-----------+                             |               |                           +-------+---+   |
    |                                           |               |                                   |       |
    |      ^             +------------------+   |               |       +--------------+            |       |
    |      |             |GenericImplFilter |   |               |       |GenericFilter | <----------+       |
    |      +-------------+                  | <-------------------------+              |                    |
    |                    +------------------+   |               |       +--------------+                    |
    |                                           |               |                                           |
    |                                           |               |                                           |
    |                                           |               |                                           |
    |                                           |               |                                           |
    +-------------------------------------------+               +-------------------------------------------+
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 基于PojoUtils 简化复杂对象,不用引入二方包。
    • 针对 com.alibaba.dubbo.rpc.service.GenericService.$invoke(String method, String[] parameterTypes, Object[] args) 这个接口进行特殊判断,基于拦截器处理特殊拦截。
    • 基于拦截器,消费者端 GenericImplFilter 处理(不考虑dubbo 其他的复杂序列化的需求很简单,基本上啥都不做)
    • 基于拦截器,服务提供者端 GenericFilter处理,>1 基于接口、方法名称、方法参数类型查询具体的服务、服务的方法名称; 2> 基于PojoUtils 、方法参数类型、方法参数 反序列化为复杂的参数对象PojoUtils.realize(args, params, method.getGenericParameterTypes()) ;3、基于PojoUtils.generalize(appResponse.getValue()) 序列化返回值。

    简单实现泛化的过滤器

    消费者端
    /**
     * GenericImplInvokerFilter 基于官方的class 2.7.2 删掉不要的东西,简化理解
     */
    @Activate(group = CommonConstants.CONSUMER, value = GENERIC_KEY, order = 20000)
    public class GenericImplFilter extends ListenableFilter {
    
        private static final Logger logger = LoggerFactory.getLogger(GenericImplFilter.class);
    
        private static final Class[] GENERIC_PARAMETER_TYPES = new Class[]{String.class, String[].class, Object[].class};
    
        public GenericImplFilter() {
            super.listener = new GenericImplListener();
        }
    
        @Override
        public Result invoke(Invoker invoker, Invocation invocation) throws RpcException {
            String generic = invoker.getUrl().getParameter(GENERIC_KEY);
            if ((invocation.getMethodName().equals($INVOKE) || invocation.getMethodName().equals($INVOKE_ASYNC))
                    && invocation.getArguments() != null
                    && invocation.getArguments().length == 3
                    && ProtocolUtils.isGeneric(generic)) {
    
                invocation.setAttachment(
                        GENERIC_KEY, invoker.getUrl().getParameter(GENERIC_KEY));
            }
            return invoker.invoke(invocation);
        }
    
        static class GenericImplListener implements Listener {
            @Override
            public void onResponse(Result appResponse, Invoker invoker, Invocation invocation) {
                
            }
    
            @Override
            public void onError(Throwable t, Invoker invoker, Invocation invocation) {
    
            }
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    生产者端
    /**
     * GenericInvokerFilter. 基于官方的class 2.7.2 删掉不要的东西,简化理解
     */
    @Activate(group = CommonConstants.PROVIDER, order = -20000)
    public class GenericFilter extends ListenableFilter {
    
        public GenericFilter() {
            super.listener = new GenericListener();
        }
    
        @Override
        public Result invoke(Invoker invoker, Invocation inv) throws RpcException {
            if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
                    && inv.getArguments() != null
                    && inv.getArguments().length == 3
                    && !GenericService.class.isAssignableFrom(invoker.getInterface())) {
                String name = ((String) inv.getArguments()[0]).trim();
                String[] types = (String[]) inv.getArguments()[1];
                Object[] args = (Object[]) inv.getArguments()[2];
                try {
                    // 找到调用的接口
                    Method method = ReflectUtils.findMethodByMethodSignature(invoker.getInterface(), name, types);
                    Class[] params = method.getParameterTypes();
                    if (args == null) {
                        args = new Object[params.length];
                    }
                    String generic = inv.getAttachment(GENERIC_KEY);
    
                    if (StringUtils.isBlank(generic)) {
                        generic = RpcContext.getContext().getAttachment(GENERIC_KEY);
                    }
    
                    if (StringUtils.isEmpty(generic)
                            || ProtocolUtils.isDefaultGenericSerialization(generic)) {
                        // 将PojoUtils 转换的简单对象 转换为复杂的对象 
                        args = PojoUtils.realize(args, params, method.getGenericParameterTypes());
                    }
                    return invoker.invoke(new RpcInvocation(method, args, inv.getAttachments()));
                } catch (NoSuchMethodException e) {
                    throw new RpcException(e.getMessage(), e);
                } catch (ClassNotFoundException e) {
                    throw new RpcException(e.getMessage(), e);
                }
            }
            return invoker.invoke(inv);
        }
    
        static class GenericListener implements Listener {
    
            @Override
            public void onResponse(Result appResponse, Invoker invoker, Invocation inv) {
                if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
                        && inv.getArguments() != null
                        && inv.getArguments().length == 3
                        && !GenericService.class.isAssignableFrom(invoker.getInterface())) {
    
                    String generic = inv.getAttachment(GENERIC_KEY);
                    if (StringUtils.isBlank(generic)) {
                        generic = RpcContext.getContext().getAttachment(GENERIC_KEY);
                    }
    
                    if (appResponse.hasException() && !(appResponse.getException() instanceof GenericException)) {
                        appResponse.setException(new GenericException(appResponse.getException()));
                    }
                    // 设置反序列化 讲复杂对象转换为简单的基础对象
                    appResponse.setValue(PojoUtils.generalize(appResponse.getValue()));
                    
                }
            }
    
            @Override
            public void onError(Throwable t, Invoker invoker, Invocation invocation) {
    
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76

    基于真实数据观察 过滤器的值的传递

    org.apache.dubbo.rpc.RpcInvocation 打印的效果,方便理解。

    public String toString() {
            return "RpcInvocation [methodName=" + methodName + ", parameterTypes="
                    + Arrays.toString(parameterTypes) + ", arguments=" + Arrays.toString(arguments)
                    + ", attachments=" + attachments + "]";
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    消费者端GenericImplFilter观察

    org.apache.dubbo.rpc.filter.GenericImplFilter

    GenericImplFilter 消费者 invoker.getUrl()的值
    dubbo://192.168.1.3:20880/org.apache.dubbo.samples.api.GreetingService?application=Test-0519fed7-71d4-494b-b225-15f153bb79db&dubbo=2.0.2&generic=true&group=dubbo&interface=org.apache.dubbo.samples.api.GreetingService&lazy=false&pid=12632&qos-enable=false®ister.ip=192.168.1.3&side=consumer&sticky=false×tamp=1591110891800&version=1.0.0.daily
    
    • 1
    GenericImplFilter 消费者 invocation.toString()的值
    RpcInvocation 
    [methodName=$invoke,//调用的方法
    parameterTypes=[class java.lang.String, class [Ljava.lang.String;,
    class [Ljava.lang.Object;],//通用泛型的参数类型
    arguments=[sayHello, [Ljava.lang.String;@68b32e3e, [Ljava.lang.Object;@bcef303],
    attachments={}
    ]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    生产者端GenericFilter 观察

    org.apache.dubbo.rpc.filter.GenericFilter

    GenericFilter RpcInvocation的toString的值
    RpcInvocation 
    [methodName=$invoke, 
    parameterTypes=[class java.lang.String, class [Ljava.lang.String;, class [Ljava.lang.Object;],
    arguments=[sayHello, [Ljava.lang.String;@4174acb6, [Ljava.lang.Object;@5486085f],
    attachments={path=org.apache.dubbo.samples.api.GreetingService, 
    input=351, dubbo=2.0.2, 
    interface=org.apache.dubbo.samples.api.GreetingService, 
    version=1.0.0.daily, generic=true, 
    group=dubbo}]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    GenericFilter invoker.getUrl()
    dubbo://192.168.1.3:20880/org.apache.dubbo.samples.api.GreetingService?anyhost=true&application=zookeeper-demo-provider&bean.name=ServiceBean:org.apache.dubbo.samples.api.GreetingService:1.0.0.daily:dubbo&bind.ip=192.168.1.3&bind.port=20880&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&group=dubbo&interface=org.apache.dubbo.samples.api.GreetingService&methods=sayHello,getListUserIncludeMe&pid=12595&qos-accept-foreign-ip=false®ister=true&release=2.7.2&revision=1.0.0.daily&side=provider×tamp=1591110149299&version=1.0.0.daily
    
    • 1

    4、总结

    对于dubbo的泛化调用的文章一直想记录一篇,一直苦于没有思路,不知道怎么找到合适的切入角来描述这个问题,正好最近协助同事排查问题,正好有所收获,因此记录一篇博客,在了解过程中不断的进化,加深了对于dubbo的认知。6-2 号,特殊的日子,好像是我阳历的生日 happy ~~

  • 相关阅读:
    PCL入门(四):kdtree简单介绍和使用
    Spring Cloud(十四):微服务灰度发布 --- Discovery
    c++ opencv将彩色图像按连通域区分
    [附源码]计算机毕业设计springboot兴达五金日杂批发商店管理系统
    java计算机毕业设计ssm+vue东莞大益球队管理系统
    Mendix与JEECG对比
    Docker套件之Mysql服务配置
    [go 面试] Go Kit中读取原始HTTP请求体的方法
    flask-admin菜鸟学习笔记
    Faster-RCNN论文解读
  • 原文地址:https://blog.csdn.net/m0_67401153/article/details/126656362