文章目录
前言
注:前言大部分摘自dubbo官网
0.1 dubbo的诞生和发展
dubbo的发展有四个过程
- 诞生阿里:2008年在阿里内部诞生,2011年开源,2012年发布2.5.3版本后停止更新
- 当当续命:2014年当当发布dubbox,是基于阿里开源的dubbo 2.5.3版本增加rest协议的dubbo版本,已于2017年停止更新
- apache毕业:2017年阿里重启dubbo项目,2018年1月,Dubbo 2.6.0版本发布,新版本将Dubbox进行了合并,2018年2月进入apache孵化,2019年毕业成为apache顶级项目
- 拥抱云原生(CloudNative):2021年 Dubbo3.0发布,标志着 Apache Dubbo 正式进入云原生时代。3.0 在通信协议、服务发现、部署架构、服务治理上都对云原生基础设施进行了全面适配, 提供了Triple、应用级服务发现、Dubbo Mesh等核心特性
0.2 为什么使用dubbo
在互联网的发展过程中,在以前,我们只需要一个服务器,将程序全部打包好就可以,但是,随着流量的增大,常规的垂直应用架构 已无法应对,所以,架构就发生了演变,从单体应用转向分布式、微服务架构。dubbo正是一款微服务开发框架,它提供了 RPC通信 与 微服务治理 两大关键能力。
-
单一应用架构
当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。此时,用于简化增删改查工作量的数据访问框架(ORM)是关键。
-
垂直应用架构
当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,提升效率的方法之一是将应用拆成互不相干的几个应用,以提升效率。此时,用于加速前端页面开发的Web框架(MVC)是关键。
-
分布式服务架构
当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。此时,用于提高业务复用及整合的分布式服务框架(RPC)是关键。
-
流动计算架构
当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。此时,用于提高机器利用率的资源调度和治理中心(SOA)是关键。
0.3 dubbo要解决的需求
- 服务注册:将提供某个服务的模块信息(通常是这个服务的ip和端口)注册到1个公共的组件(zookeeper)上去
- 服务发现:新注册的这个服务模块能够及时的被其他调用者发现。不管是服务新增和服务删减都能实现自动发现
- 服务降级:将某些服务停掉或者不进行业务处理,释放资源来维持主要服务的功能
- 服务路由:服务路由包含一条路由规则,路由规则决定了服务消费者的调用目标,即规定了服务消费者可调用哪些服务提供者
- 服务容量评估:衡量服务容量的指标:单机QPS、峰值、平均值、用户数、并发、稳定性
- 服务质量协定:服务质量等级协定(SLA),SLA包括消费者承诺每天调用量,请求数据量,提供方承诺响应时间,出错率等
- 软负载均衡:指软件负载均衡,是通过在服务器上安装的特定的负载均衡软件或是自带负载均衡模块完成对请求的分配派发
在大规模服务化之前,应用可能只是通过 RMI 或 Hessian 等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过 F5 等硬件进行负载均衡
-
当服务越来越多时,服务 URL 配置管理变得非常困难,F5 硬件负载均衡器的单点压力也越来越大。 此时需要一个服务注册中心,动态地注册和发现服务,使服务的位置透明。并通过在消费方获取服务提供方地址列表,实现软负载均衡和 Failover,降低对 F5 硬件负载均衡器的依赖,也能减少部分成本。
-
当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。 这时,需要自动画出应用间的依赖关系图,以帮助架构师理清关系。
-
接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器? 为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阈值,记录此时的访问量,再以此访问量乘以机器数反推总容量。
以上是 Dubbo 最基本的几个需求
0.4 dubbo架构
节点角色说明
节点 | 角色说明 |
---|---|
Provider | 暴露服务的服务提供方 |
Consumer | 调用远程服务的服务消费方 |
Registry | 服务注册与发现的注册中心 |
Monitor | 统计服务的调用次数和调用时间的监控中心 |
Container | 服务运行容器 |
调用关系说明
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
一、Dubbo + SpringBoot
Dubbo 采用全 Spring 配置方式,透明化接入应用,对应用没有任何 API 侵入,只需用 Spring 加载 Dubbo 的配置即可,Dubbo 基于 Spring 的 Schema 扩展 进行加载。
Dubbo官方文档示例大都是Spring xml配置,在SpringBoot中也可以使用@ImportResource
导入xml文件, 不过一般在SpringBoot中采用的是注解和yml配置。
在https://github.com/apache/dubbo-spring-boot-project/tree/master/dubbo-spring-boot-samples有官方给的dubbo+springboot的例子
1.1 多模块pom
分布式架构必定要拆分原有的单体项目结构,以maven为例,就要构造一个多模块项目,下面以一个小例子说明。
dubboDemo:父项目的打包方式要为pom, 使用dependencyManagement管理子项目依赖版本,这样子项目就不用指定具体版本了
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.aabond</groupId>
<artifactId>dubbodemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>dubbodemo</name>
<description>dubbodemo</description>
<packaging>pom</packaging>
<properties>
<spring-boot.version>2.3.0.RELEASE</spring-boot.version>
<dubbo.version>2.7.8</dubbo.version>
<dubbo-spring-boot.version>2.7.8</dubbo-spring-boot.version>
<curator.famework.version>4.2.0</curator.famework.version>
</properties>
<modules>
<module>api</module>
<module>consumer</module>
<module>provider</module>
</modules>
<dependencyManagement>
<dependencies>
<!-- Spring Boot -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-dependencies</artifactId>
<version>${spring-boot.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<!-- Apache Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo-spring-boot.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>${curator.famework.version}</version>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
<version>${curator.famework.version}</version>
</dependency>
</dependencies>
</dependencyManagement>
</project>
api:将接口单独抽出来作为一个项目,方便consumer和provider引用,顺便将通用的依赖可以放入这里,减少重复配置
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.aabond</groupId>
<artifactId>dubbodemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>api</name>
<description>api</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
consumer:消费者
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.aabond</groupId>
<artifactId>dubbodemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>consumer</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>consumer</name>
<description>consumer</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.aabond</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
provider:生产者
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.aabond</groupId>
<artifactId>dubbodemo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>provider</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>provider</name>
<description>provider</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>com.aabond</groupId>
<artifactId>api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
</project>
1.2 配置
-
yml和注解配置
以dubbo开头,具体属性可以通过提示或者从
DubboConfigurationProperties
这个类获取dubbo: application: name: provider # 服务名,默认spring.application.name registry: address: zookeeper://127.0.0.1:2181 # 注册中心地址,使用zookeeper protocol: # 连接协议用于服务调用 port: 20881 name: dubbo #采用dubbo协议,暴露端口为20881 monitor: # 监控中心 protocol: registry #从注册中心找到监控中心
主要就三个注解
-
@DubboService
早前版本是@Service,在2.7.7版本被废弃,标记类是参与dubbo RPC服务调用的类
-
@DubboReference
早前版本是@Reference,在2.7.7版本被废弃,类似@autowire,不过是RPC调用
-
@EnableDubbo
是
@EnableDubboConfig
和@DubboComponentScan
的组合, 扫描标记@DubboService的类和开启DubboConfig
-
-
xml配置
-
详细见官方文档,https://dubbo.apache.org/zh/docsv2.7/user/configuration/xml/
-
生产者示例
<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.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <dubbo:application name="provider"/> <dubbo:registry address="zookeeper://127.0.0.1:2181"/> <dubbo:protocol name="dubbo" port="20881"/> <bean id="helloService" class="com.aabond.provider.service.impl.HelloServiceImpl"/> <dubbo:service interface="com.aabond.api.HelloService" ref="helloService"/> </beans>
-
消费者示例
<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.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"> <dubbo:application name="consumer"/> <dubbo:registry group="aaa" address="zookeeper://127.0.0.1:2181"/> <dubbo:reference id="helloService" check="false" interface="com.aabond.api.HelloService"/> </beans>
-
xml标签使用
标签 用途 解释 <dubbo:service/>
服务配置 用于暴露一个服务,定义服务的元信息,一个服务可以用多个协议暴露,一个服务也可以注册到多个注册中心 <dubbo:reference/>
引用配置 用于创建一个远程服务代理,一个引用可以指向多个注册中心 <dubbo:protocol/>
协议配置 用于配置提供服务的协议信息,协议由提供方指定,消费方被动接受 <dubbo:application/>
应用配置 用于配置当前应用信息,不管该应用是提供者还是消费者 <dubbo:module/>
模块配置 用于配置当前模块信息,可选 <dubbo:registry/>
注册中心配置 用于配置连接注册中心相关信息 <dubbo:monitor/>
监控中心配置 用于配置连接监控中心相关信息,可选 <dubbo:provider/>
提供方配置 当 ProtocolConfig 和 ServiceConfig 某属性没有配置时,采用此缺省值,可选 <dubbo:consumer/>
消费方配置 当 ReferenceConfig 某属性没有配置时,采用此缺省值,可选 <dubbo:method/>
方法配置 用于 ServiceConfig 和 ReferenceConfig 指定方法级的配置信息 <dubbo:argument/>
参数配置 用于指定方法参数配置
-
二、RPC调用
2.1 Zookeeper
Zookeeper可被dubbo作为注册中心,主要用于服务的注册与发现。
启用Zookeeper一般有两种,一种是使用内嵌Zookeeper,另一种是下载Zookeeper,作为独立的第三方组件使用
第一种在官方例子中有示例,这里介绍第二种
- 下载Zookeeper
- 修改配置文件
- 将conf/zoo_sample.cfg修改为conf/zoo.cfg
- 添加一行
server.1=localhost:2888:3888
,2888是与集群leader交换信息端口,3888是选举leader端口。也可以修改clientPort=2181,这里暂不修改
- 运行
- windows执行bin/zkServer.cmd, linux执行bin\zkServer.sh
- windows下做成服务
- 使用https://github.com/winsw/winsw
2.2 编译并启动
三个子project代码如下
-
api
public interface HelloService { String sayHello(String name); }
-
consumer
@RequestMapping("/") @RestController public class HelloController { @DubboReference(version = "1.0.0", timeout = 300) private HelloService helloService; @GetMapping("/sayHello/{name}") public String sayHello(@PathVariable(name = "name")String name) { return helloService.sayHello(name); } }
@SpringBootApplication @EnableDubbo public class ConsumerApplication { public static void main(String[] args) { SpringApplication.run(ConsumerApplication.class, args); } }
server: port: 8081 dubbo: application: name: consumer registry: address: zookeeper://127.0.0.1:2181 monitor: protocol: registry
-
provider
@DubboService(version = "1.0.0") @Service public class HelloServiceImpl implements HelloService { private static final Logger logger = LoggerFactory.getLogger(HelloServiceImpl.class); private final Random costTimeRandom = new Random(); @Value("${dubbo.application.name}") private String serviceName; @Override public String sayHello(String name) { await(); return String.format("[%s] : Hello, %s", serviceName, name); } private void await() { try { long timeInMillisToWait = costTimeRandom.nextInt(500); Thread.sleep(timeInMillisToWait); logger.info("execution time : " + timeInMillisToWait + " ms."); } catch (InterruptedException e) { throw new RuntimeException(e); } } }
@SpringBootApplication @EnableDubbo public class ProviderApplication { public static void main(String[] args) { SpringApplication.run(ProviderApplication.class, args); } }
dubbo: application: name: provider registry: address: zookeeper://127.0.0.1:2181 protocol: port: 20881 name: dubbo monitor: protocol: registry
先要编译api,install完成后,依次compile就可以run了
三、微服务治理
可通过编辑代码、配置文件和dubbo-admin来实现
3.1 服务分组
当一个接口有多种实现时,可以用 group 区分
可以在注解中添加group
@DubboReference(group = "hello1", check = false)
private HelloService helloService1;
@DubboReference(group = "hello2", check = false)
private HelloService helloService2;
3.2 版本号
当同一个服务分组的接口实现,出现不兼容升级时,可以用版本号过渡,版本号不同的服务相互间不引用。
在Dubbo中接口并不能唯一确定一个服务,在dubbo中接口+服务分组+版本号才能唯一确定一个服务
可以在注解中添加version
@DubboReference(version = "1.0.0", timeout = 300)
private HelloService helloService;
3.3 多协议
Dubbo 允许配置多协议,在不同服务上支持不同协议或者同一服务上同时支持多种协议。
不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议
可以在注解或配置文件中配置
@DubboReference(protocol = "dubbo")
private RpcWrapperService rpcWrapperService;
@DubboReference(protocol = "rmi")
private ProtocolDemoServiceClient protocolDemoServiceClient;
3.4 服务超时重试
Dubbo 服务在尝试调用一次之后,如出现非业务异常(服务突然不可用、超时等),Dubbo 默认会进行额外的最多2次重试.
可以在注解上添加retries=n
@DubboService(version = "1.0.0", retries = 3, timeout = 300)
@Service
public class HelloServiceImpl implements HelloService {
}
3.5 服务路由
官方文档: https://dubbo.apache.org/zh/docs/advanced/routing-rule/
-
条件路由可以编写一些自定义路由规则实现一些服务治理的需求比如黑白名单、读写分离等。条件路由可以在接口级别和消费者应用级别创建规则
-
标签路由通过将某一个或多个服务的提供者划分到同一个分组,约束流量只在指定分组中流转,从而实现流量隔离的目的,可以作为蓝绿发布、灰度发布等场景的能力基础
通过dubbo-admin
3.6 服务测试
通过dubbo-admin
3.7 服务降级
可以通过服务降级功能临时屏蔽某个出错的非关键服务,并定义降级后的返回策略。
向注册中心写入动态配置覆盖规则:
configVersion: v2.7
scope: service
key: org.apache.dubbo.samples.governance.api.DemoService
enabled: true
configs:
- side: consumer
parameters:
force: return null
force:return+null
表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。- 还可以改为
mock=fail:return+null
表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
通过dubbo-admin或者注解
@DubboReference(mock="force:return null")
private HelloService helloService;
3.8 动态配置
提供了无须重启可以动态调整 RPC 调用行为的一种能力。比如修改超时时间、权重、负载均衡策略调整等
官方文档:https://dubbo.apache.org/zh/docs/advanced/config-rule/
3.9 集群容错
在集群调用失败时,Dubbo 提供了多种容错方案。
-
Failover Cluster
失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过
retries="2"
来设置重试次数(不含第一次) -
Failfast Cluster
快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。
-
Failsafe Cluster
失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。
-
Failback Cluster
失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
-
Forking Cluster
并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过
forks="2"
来设置最大并行数。 -
Broadcast Cluster
广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。
默认为 Failover Cluster
通过注解
@DubboReference(cluster = "failsafe")
private HelloService helloService;
3.10 负载均衡
在集群负载均衡时,Dubbo 提供了多种均衡策略,
算法 | 特性 | 备注 |
---|---|---|
RandomLoadBalance | 加权随机 | 默认算法,默认权重相同 |
RoundRobinLoadBalance | 加权轮询 | 借鉴于 Nginx 的平滑加权轮询算法,默认权重相同, |
LeastActiveLoadBalance | 最少活跃优先 + 加权随机 | 背后是能者多劳的思想 |
ShortestResponseLoadBalance | 最短响应优先 + 加权随机 | 更加关注响应速度 |
ConsistentHashLoadBalance | 一致性 Hash | 确定的入参,确定的提供者,适用于有状态请求 |
默认为 Random
通过注解 @DubboReference 或配置文件
@DubboReference(version = "${demo.service.version}" ,loadbalance = "roundrobin",group = "myGroup")
private DemoService demoService;
更多用法可以见:https://dubbo.apache.org/zh/docsv2.7/user/examples/