写点什么

Dubbo 泛化引用

用户头像
青年IT男
关注
发布于: 2021 年 05 月 09 日
Dubbo 泛化引用

前言

大家好,今天开始给大家分享 — Dubbo 专题之 Dubbo 泛化引用。在前一个章节中我们介绍了 Dubbo 中的参数验证以及使用场景。我们在这个章节会继续介绍 Dubbo 泛化引用。那么什么是泛化引用呢?泛化引用有什么作用呢?下面就让我详细了解下吧!

1. 泛化引用简介

在前面的章节中我们编写的 Dubbo 服务都是基于 API 接口,例如:com.muke.dubbocourse.common.api.BookFacade接口。我们在日常开发中的步骤都是首先定义好暴露服务的 API 接口,然后把这个接口打包成 jar 提供给服务调用方。也就是说通常情况下我们的服务调用方都会依赖我们定义的 API 接口编程。那么在 Dubbo 中为我们提供一种不需要依赖 API 接口的方式进行服务调用,这种方式就泛化引用。其表示类为GenericService

2. 使用方式

在这里我们主要介绍两种使用方式:


  1. 通过 Spring 使用泛化引用


  • 配置 XML 文件中的服务引用为generic="true"


  <dubbo:reference id="barService" interface="com.muke.dubbocourse.common.api.BookFacade" generic="true" />
复制代码


  • 在代码中使用泛化调用


  GenericService barService = (GenericService) applicationContext.getBean("bookFacade");  Object result = barService.$invoke("queryAll", null, null);
复制代码


  1. 通过 Java API 方式使用


// 引用远程服务 ReferenceConfig<GenericService> reference = new ReferenceConfig<GenericService>(); // 弱类型接口名reference.setInterface("com.muke.dubbocourse.common.api.BookFacade");  reference.setVersion("0.0.1");// 声明为泛化接口 reference.setGeneric(true);  
// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用 GenericService genericService = reference.get();
// 如果返回实体对象将自动转成Map Object result = genericService.$invoke("queryByName",new String[]{"com.muke.dubbocourse.common.api.RequestParameter"}, new Object[]{parameter});
复制代码

3. 使用场景

从泛化引用本身我们可以知道它是不需要 API 接口,也就是说泛化引用使用场景在服务提供方没有明确的 API 接口提供的情况下我们都可以使用。通常用于框架集成,比如:实现一个 Dubbo 服务对外统一网,就可通过 GenericService 调用后端所有服务实现。 例如:



在上面的图中客户端通过统一的 Dubbo 网关访问后端所有的 Dubbo 服务,这里就是使用 泛化调用实现。

4. 示例演示

下面我们通过两种方式来演示一个获取图书列表的服务。


  1. 使用 Spring 泛化引用


  • 主要看消费端 XML 配置文件dubbo-consumer-xml.xml


  <?xml version="1.0" encoding="UTF-8"?>  <beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"         xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"         xmlns="http://www.springframework.org/schema/beans"         xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-4.3.xsd         http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd">        <dubbo:application name="demo-consumer" logger="log4j"/>        <!--使用zookeeper注册中心-->      <dubbo:registry address="zookeeper://127.0.0.1:2181" />      <!--设置generic="true"-->      <dubbo:reference id="bookFacade" interface="com.muke.dubbocourse.common.api.BookFacade" generic="true"></dubbo:reference>    </beans>
复制代码


  • 消费端 Java 代码


  public class XmlApplication {        public static void main(String[] args) throws IOException {            ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("generic/consumer/spring/dubbo-consumer-xml.xml");            context.start();            //创建泛化调用对象          GenericService bookFacade = (GenericService) context.getBean("bookFacade");            RequestParameter parameter = new RequestParameter();            parameter.setName("SpringBoot");          //泛化调用 第一个参数:方法名称,第二个参数:请求参数类型的数组,第三方个参数:请求参数值的数组          Object result = bookFacade.$invoke("queryByName", new String[] { "com.muke.dubbocourse.common.api.RequestParameter" }, new Object[] { parameter });            System.out.println("Result=>"+result);            System.in.read();        }    }
复制代码


  1. 使用 Java API 方式


public class XmlApplication2 {
public static void main(String[] args) throws IOException {
// 引用远程服务 ReferenceConfig<GenericService> reference = new ReferenceConfig<>(); // 弱类型接口名 reference.setInterface("com.muke.dubbocourse.common.api.BookFacade");
//注册中心配置 RegistryConfig registryConfig = new RegistryConfig();
registryConfig.setAddress("zookeeper://127.0.0.1:2181");
reference.setRegistry(registryConfig);
//应用配置 ApplicationConfig applicationConfig = new ApplicationConfig();
applicationConfig.setName("demo-consumer");
reference.setApplication(applicationConfig); // 声明为泛化接口 reference.setGeneric(true);
// 用org.apache.dubbo.rpc.service.GenericService可以替代所有接口引用 GenericService genericService = reference.get();
RequestParameter parameter = new RequestParameter();
parameter.setName("SpringBoot");
Object result = genericService.$invoke("queryByName", new String[]{"com.muke.dubbocourse.common.api.RequestParameter"}, new Object[]{parameter});
System.out.println("Result=>" + result);
System.in.read();
}
}
复制代码


在上面的代码中我们通过 Java API 的方式配置了注册中心、应用配置。在调用服务的使用和上面的 Spring 使用方式类似使用org.apache.dubbo.rpc.service.GenericService#$invoke方法。

5. 实现原理

在上面的代码GenericService genericService = reference.get()中会调用到org.apache.dubbo.config.ReferenceConfig#init方法,而在此方法中org.apache.dubbo.config.ReferenceConfig#createProxy方法创建一个服务调用代理对象。当我们调用genericService.$invoke方法是实际调用的是org.apache.dubbo.rpc.proxy.InvokerInvocationHandler#invoke方法然后调用org.apache.dubbo.rpc.cluster.support.wrapper.MockClusterInvoker#invoke调用我们org.apache.dubbo.rpc.cluster.support.AbstractClusterInvoker#invoke在此方法中就查找我们的调用远程的 Invoker 对象,时序图如下:




6. 小结

在本小节中我们主要学习了 Dubbo 中泛化引用和使用场景,以及使用 Spring 的方式和基于 Java API 的方式使用泛化引用。同时也分析了泛化引用实现的原理,其实就是通过ReferenceConfig包装接口名称、调用方法以及参数名称和参数值,再创建GenericService代理对象然后调用一系列的 Invoker 对象。


本节课程的重点如下:


  1. 理解 Dubbo 中泛化引用

  2. 了解了两种泛化引用使用方式

  3. 了解泛化引用实现原理

  4. 了解泛化引用使用场景

作者

个人从事金融行业,就职过易极付、思建科技、某网约车平台等重庆一流技术团队,目前就职于某银行负责统一支付系统建设。自身对金融行业有强烈的爱好。同时也实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域。同时也热衷于技术分享创立公众号和博客站点对知识体系进行分享。关注公众号:青年 IT 男 获取最新技术文章推送!


博客地址: http://youngitman.tech


微信公众号:



发布于: 2021 年 05 月 09 日阅读数: 24
用户头像

青年IT男

关注

站在巨人肩上看得更远! 2018.04.25 加入

从事金融行业,就职过易极付、思建科技、网约车平台等一流技术团队,目前就职于银行负责支付系统建设。对金融行业有强烈的爱好。实践大数据、数据存储、自动化集成和部署、分布式微服务、响应式编程、人工智能等领域

评论

发布
暂无评论
Dubbo 泛化引用