不使用他人jar包情况下优雅的进行dubbo调用详解

 更新时间:2022年09月28日 14:10:21   作者:spider集控团队  
这篇文章主要为大家介绍了不使用他人jar包情况下优雅的进行dubbo调用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

1、正常dubbo调用流程

  • 引入dubbo依赖
  • 引入他人提供的clinet依赖包;
  • 配置相同的注册中心,使用@Reference注解注入对应的service接口(注意是Reference是dubbo包下的,不是spring那个)

2、如果想在不引用他人jar包的情况下如何调用呢?

dubbo泛化调用-dubbo原生支持的优雅方法

使用场景:

  • 消费者不希望引入生产者提供的clinet依赖; 例如:消费者是一个基础服务,需要调用很多生产者的dubbo方法,那他就要引入很多的jar包;
  • 消费者不使用java语言,而是使用其他的语言(例如:Python);

如何使用:

1.需要知道对方方法的全路径名称(interfaceName)

2.如果对方的dubbo有指定的版本号(version)和组(group)要指定一下,不然有很大可能会调用不通

3.要知道对方的注册中心地址和连接方式(如果是在同一个zk注册中心就更好了)

//1.获取泛化对象
private GenericService getGenericService(String interfaceName, String version, String group) {
    ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>();
    // set application
    ApplicationConfig applicationConfig = new ApplicationConfig();
    applicationConfig.setId(APPLICATION_ID);
    applicationConfig.setName(APPLICATION_ID);
    reference.setApplication(applicationConfig);
    // 通过zookeeper连接
    RegistryConfig registryConfig = new RegistryConfig();
    registryConfig.setAddress(zkAddress);
    registryConfig.setProtocol(ZOOKEEPER);
    registryConfig.setCheck(false);
    reference.setRegistry(registryConfig);
    // set timeout
    reference.setTimeout(syncForwardTimeout);
    // set retry times
    reference.setRetries(syncRetries);
    // set check
    reference.setCheck(false);
    // set generic
    reference.setGeneric(true);
    // set interface version
    if (version != null && version.length() != 0) {
        reference.setVersion(version);
    }
    // set interface name
    reference.setInterface(interfaceName);
    // set service id
    reference.setId(interfaceName);
    // set dubbo protocol
    reference.setProtocol(DUBBO);
    //
    if (group != null && group.length() != 0) {
        reference.setGroup(group);
    }
    // 从zookeeper获取缓存,从缓存中获取泛化
    return ReferenceConfigCache.getCache().get(reference);
}
//2.泛化调用入参处理
```
private ResponseDataDto<R> invoke(GenericService genericService, UpDataReqDto upDataReqDto, String method) {
    String[] paramTypes = new String[1];
    Object[] paramValues = new Object[1];
    int i = 0;
    paramTypes[i] = upDataReqDto.getClass().getTypeName();
    paramValues[i] = upDataReqDto;
    Object object = genericService.$invoke(method, paramTypes, paramValues);
    return JSON.parseObject(JSON.toJSONString(object), new TypeReference<ResponseDataDto<R>>(){});
}
```

实现原理:

  • 泛化调用的实现主要涉及两个filter
1.  com.alibaba.dubbo.rpc.filter.GenericFilter
2.  com.alibaba.dubbo.rpc.filter.GenericImplFilter
  • 泛化调用的流程:
  • 调用 <-> GenericImplFilter <-> 网络(RPC) <-> GenericFilter <-> 服务实现
  • 泛化调用的核心源码:
GenericImplFilter:
```
//判断是不是泛化调用
if (isCallingGenericImpl(generic, invocation)) {
    RpcInvocation invocation2 = new RpcInvocation(invocation);
    /**
     * Mark this invocation as a generic impl call, this value will be removed automatically before passing on the wire.
     * See {@link RpcUtils#sieveUnnecessaryAttachments(Invocation)}
     */
    invocation2.put(GENERIC_IMPL_MARKER, true);
    String methodName = invocation2.getMethodName();
    Class<?>[] parameterTypes = invocation2.getParameterTypes();
    Object[] arguments = invocation2.getArguments();
    String[] types = new String[parameterTypes.length];
    for (int i = 0; i < parameterTypes.length; i++) {
        types[i] = ReflectUtils.getName(parameterTypes[i]);
    }
    Object[] args;
    if (ProtocolUtils.isBeanGenericSerialization(generic)) {
        args = new Object[arguments.length];
        for (int i = 0; i < arguments.length; i++) {
            args[i] = JavaBeanSerializeUtil.serialize(arguments[i], JavaBeanAccessor.METHOD);
        }
    } else {
        args = PojoUtils.generalize(arguments);
    }
    if (RpcUtils.isReturnTypeFuture(invocation)) {
        invocation2.setMethodName($INVOKE_ASYNC);
    } else {
        invocation2.setMethodName($INVOKE);
    }
    invocation2.setParameterTypes(GENERIC_PARAMETER_TYPES);
    invocation2.setParameterTypesDesc(GENERIC_PARAMETER_DESC);
    invocation2.setArguments(new Object[]{methodName, types, args});
    return invoker.invoke(invocation2);
}
// 普通服务进行通用调用
else if (isMakingGenericCall(generic, invocation)) {
    Object[] args = (Object[]) invocation.getArguments()[2];
    if (ProtocolUtils.isJavaGenericSerialization(generic)) {
        for (Object arg : args) {
            if (byte[].class != arg.getClass()) {
                error(generic, byte[].class.getName(), arg.getClass().getName());
            }
        }
    } else if (ProtocolUtils.isBeanGenericSerialization(generic)) {
        for (Object arg : args) {
            if (!(arg instanceof JavaBeanDescriptor)) {
                error(generic, JavaBeanDescriptor.class.getName(), arg.getClass().getName());
            }
        }
    }
    invocation.setAttachment(
            GENERIC_KEY, invoker.getUrl().getParameter(GENERIC_KEY));
}
GenericFilter:
if ((inv.getMethodName().equals($INVOKE) || inv.getMethodName().equals($INVOKE_ASYNC))
    && inv.getArguments() != null
    && inv.getArguments().length == 3
    && !GenericService.class.isAssignableFrom(invoker.getInterface())){
    .......泛化调用处理逻辑......
    }

3、总结

  • 从源码设计来看泛化调用提供了在没有接口依赖的情况下进行调用的解决方案;
  • 从扩展上来看泛化调用的侵入性不强,可以很好的用于框架扩展;

以上就是不使用他人jar包情况下优雅的进行dubbo调用详解的详细内容,更多关于不引用jar包调用dubbo的资料请关注脚本之家其它相关文章!

相关文章

  • 如何解决Java多线程死锁问题

    如何解决Java多线程死锁问题

    死锁是一个很严重的、必须要引起重视的问题,本文主要介绍了死锁的定义,解决方法和面试会遇到的问题,感兴趣的可以了解一下
    2021-05-05
  • java生成指定范围的随机日期

    java生成指定范围的随机日期

    这篇文章主要为大家详细介绍了java生成指定范围的随机日期,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2017-12-12
  • SpringBoot中@ConfigurationProperties注解实现配置绑定的三种方法

    SpringBoot中@ConfigurationProperties注解实现配置绑定的三种方法

    这篇文章主要介绍了SpringBoot中@ConfigurationProperties注解实现配置绑定的三种方法,文章内容介绍详细需要的小伙伴可以参考一下
    2022-04-04
  • java8从list集合中取出某一属性的值的集合案例

    java8从list集合中取出某一属性的值的集合案例

    这篇文章主要介绍了java8从list集合中取出某一属性的值的集合案例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-08-08
  • SpringBoot中Get请求和POST请求接收参数示例详解

    SpringBoot中Get请求和POST请求接收参数示例详解

    文章详细介绍了SpringBoot中Get请求和POST请求的参数接收方式,包括方法形参接收参数、实体类接收参数、HttpServletRequest接收参数、@PathVariable接收参数、数组参数接收、集合参数接收、Map接收参数以及通过@RequestBody接收JSON格式的参数,感兴趣的朋友一起看看吧
    2024-12-12
  • 利用javaFX实现移动一个小球的示例代码

    利用javaFX实现移动一个小球的示例代码

    这篇文章主要介绍了利用javaFX实现移动一个小球的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-09-09
  • Java实现的简单画图板示例

    Java实现的简单画图板示例

    这篇文章主要介绍了Java实现的简单画图板,涉及java使用swing组件进行图形绘制相关操作技巧,需要的朋友可以参考下
    2018-08-08
  • java中注解的原理解析

    java中注解的原理解析

    这篇文章主要介绍了java中注解的原理解析,java 注解又称 Java 标注,是 JDK5.0 引入的一种注释机制,可以理解为为某个东西,打个标记的记号,等要使用这个注解时,可以通过反射获取标注里面的内容,需要的朋友可以参考下
    2023-10-10
  • Spring实现动态修改时间参数并手动开启关停操作

    Spring实现动态修改时间参数并手动开启关停操作

    spring实现定时任务的方式有三种,分别是java自带的timer类、spring task和quartz三种。本文只介绍spring自带的task和第三方quartz,感兴趣的朋友参考下吧
    2017-09-09
  • Java中DateTimeFormatter的使用方法和案例

    Java中DateTimeFormatter的使用方法和案例

    在Java中,DateTimeFormatter类用于格式化和解析日期时间对象,它是日期时间格式化的强大而灵活的工具,本文将和大家一起探讨Java中DateTimeFormatter的使用方法和案例,需要的朋友可以参考下
    2023-10-10

最新评论