Dubbo(概述)

Dubbo(概述)



dubbo官网:http://dubbo.io/

dubbo github代码:dubbo github代码
当当版dubbox 代码:当当版dubbox 代码
dubbo源码解析:dubbo源码解析

入门

(+) (#)

背景

(#)

随着互联网的发展,网站应用的规模不断扩大,常规的垂直应用架构已无法应对,分布式服务架构以及流动计算架构势在必行,亟需一个治理系统确保架构有条不紊的演进。

  • 单一应用架构
    • 当网站流量很小时,只需一个应用,将所有功能都部署在一起,以减少部署节点和成本。
    • 此时,用于简化增删改查工作量的 数据访问框架(ORM) 是关键。
  • 垂直应用架构
    • 当访问量逐渐增大,单一应用增加机器带来的加速度越来越小,将应用拆成互不相干的几个应用,以提升效率。
    • 此时,用于加速前端页面开发的 Web框架(MVC) 是关键。
  • 分布式服务架构
    • 当垂直应用越来越多,应用之间交互不可避免,将核心业务抽取出来,作为独立的服务,逐渐形成稳定的服务中心,使前端应用能更快速的响应多变的市场需求。
    • 此时,用于提高业务复用及整合的 分布式服务框架(RPC) 是关键。
  • 流动计算架构
    • 当服务越来越多,容量的评估,小服务资源的浪费等问题逐渐显现,此时需增加一个调度中心基于访问压力实时管理集群容量,提高集群利用率。
    • 此时,用于提高机器利用率的 资源调度和治理中心(SOA) 是关键。

需求

(#)

在大规模服务化之前,应用可能只是通过RMI或Hessian等工具,简单的暴露和引用远程服务,通过配置服务的URL地址进行调用,通过F5等硬件进行负载均衡。

(1) 当服务越来越多时,服务URL配置管理变得非常困难,F5硬件负载均衡器的单点压力也越来越大。

此时需要一个服务注册中心,动态的注册和发现服务,使服务的位置透明。

并通过在消费方获取服务提供方地址列表,实现软负载均衡和Failover,降低对F5硬件负载均衡器的依赖,也能减少部分成本。

(2) 当进一步发展,服务间依赖关系变得错踪复杂,甚至分不清哪个应用要在哪个应用之前启动,架构师都不能完整的描述应用的架构关系。

这时,需要自动画出应用间的依赖关系图,以帮助架构师理清理关系。

(3) 接着,服务的调用量越来越大,服务的容量问题就暴露出来,这个服务需要多少机器支撑?什么时候该加机器?

为了解决这些问题,第一步,要将服务现在每天的调用量,响应时间,都统计出来,作为容量规划的参考指标。

其次,要可以动态调整权重,在线上,将某台机器的权重一直加大,并在加大的过程中记录响应时间的变化,直到响应时间到达阀值,记录此时的访问量,再以此访问量乘以机器数反推总容量。

以上是Dubbo最基本的几个需求,更多服务治理问题参见:

http://code.alibabatech.com/blog/experience_1402/service-governance-process.html

架构

(#)

节点角色说明:

  • Provider: 暴露服务的服务提供方。
  • Consumer: 调用远程服务的服务消费方。
  • Registry: 服务注册与发现的注册中心。
  • Monitor: 统计服务的调用次调和调用时间的监控中心。
  • Container: 服务运行容器。

调用关系说明:

  • 0. 服务容器负责启动,加载,运行服务提供者。
  • 1. 服务提供者在启动时,向注册中心注册自己提供的服务。
  • 2. 服务消费者在启动时,向注册中心订阅自己所需的服务。
  • 3. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
  • 4. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
  • 5. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

(1) 连通性:

  • 注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小
  • 监控中心负责统计各服务调用次数,调用时间等,统计先在内存汇总后每分钟一次发送到监控中心服务器,并以报表展示
  • 服务提供者向注册中心注册其提供的服务,并汇报调用时间到监控中心,此时间不包含网络开销
  • 服务消费者向注册中心获取服务提供者地址列表,并根据负载算法直接调用提供者,同时汇报调用时间到监控中心,此时间包含网络开销
  • 注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外
  • 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者
  • 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表
  • 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者

(2) 健状性:

  • 监控中心宕掉不影响使用,只是丢失部分采样数据
  • 数据库宕掉后,注册中心仍能通过缓存提供服务列表查询,但不能注册新服务
  • 注册中心对等集群,任意一台宕掉后,将自动切换到另一台
  • 注册中心全部宕掉后,服务提供者和服务消费者仍能通过本地缓存通讯
  • 服务提供者无状态,任意一台宕掉后,不影响使用
  • 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

(3) 伸缩性:

  • 注册中心为对等集群,可动态增加机器部署实例,所有客户端将自动发现新的注册中心
  • 服务提供者无状态,可动态增加机器部署实例,注册中心将推送新的服务提供者信息给消费者

(4) 升级性:

  • 当服务集群规模进一步扩大,带动IT治理结构进一步升级,需要实现动态部署,进行流动计算,现有分布式服务架构不会带来阻力:

  • Deployer: 自动部署服务的本地代理。
  • Repository: 仓库用于存储服务应用发布包。
  • Scheduler: 调度中心基于访问压力自动增减服务提供者。
  • Admin: 统一管理控制台。

用法

(#)

本地服务:(Spring配置)

local.xml
<beanid=“xxxService” class=“com.xxx.XxxServiceImpl” />
 
<beanid=“xxxAction” class=“com.xxx.XxxAction”>
    <propertyname=“xxxService” ref=“xxxService” />
</bean>

远程服务:(Spring配置)

在本地服务的基础上,只需做简单配置,即可完成远程化:

  • 将上面的local.xml配置拆分成两份,将服务定义部分放在服务提供方remote-provider.xml,将服务引用部分放在服务消费方remote-consumer.xml。
  • 并在提供方增加暴露服务配置<dubbo:service>,在消费方增加引用服务配置<dubbo:reference>。

如下:

remote-provider.xml
<beanid=“xxxService” class=“com.xxx.XxxServiceImpl” /><!-- 和本地服务一样实现远程服务 -->
 
<dubbo:serviceinterface=“com.xxx.XxxService” ref=“xxxService” /><!-- 增加暴露远程服务配置 -->
remote-consumer.xml
<dubbo:referenceid=“xxxService” interface=“com.xxx.XxxService” /><!-- 增加引用远程服务配置 -->
 
<beanid=“xxxAction” class=“com.xxx.XxxAction”><!-- 和本地服务一样使用远程服务 -->
    <propertyname=“xxxService” ref=“xxxService” />
</bean>

快速启动

(+) (#)

Dubbo采用全Spring配置方式,透明化接入应用,对应用没有任何API侵入,只需用Spring加载Dubbo的配置即可,Dubbo基于Spring的Schema扩展进行加载。
如果不想使用Spring配置,而希望通过API的方式进行调用(不推荐),请参见:API配置 (+)

服务提供者

(#)

完整安装步骤,请参见:示例提供者安装 (+)

定义服务接口: (该接口需单独打包,在服务提供方和消费方共享)

DemoService.java
packagecom.alibaba.dubbo.demo;
 
publicinterfaceDemoService {
 
    String sayHello(String name);
 
}

在服务提供方实现接口:(对服务消费方隐藏实现)

DemoServiceImpl.java
packagecom.alibaba.dubbo.demo.provider;
 
importcom.alibaba.dubbo.demo.DemoService;
 
publicclassDemoServiceImplimplementsDemoService {
 
    publicString sayHello(String name) {
        return"Hello "+ name;
    }
 
}

用Spring配置声明暴露服务:

provider.xml
<?xmlversion="1.0"encoding="UTF-8"?>
    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 
    <!-- 提供方应用信息,用于计算依赖关系 -->
    <dubbo:applicationname="hello-world-app" />
 
    <!-- 使用multicast广播注册中心暴露服务地址 -->
    <dubbo:registryaddress="multicast://224.5.6.7:1234"/>
 
    <!-- 用dubbo协议在20880端口暴露服务 -->
    <dubbo:protocolname="dubbo"port="20880"/>
 
    <!-- 声明需要暴露的服务接口 -->
    <dubbo:serviceinterface="com.alibaba.dubbo.demo.DemoService"ref="demoService"/>
 
    <!-- 和本地bean一样实现服务 -->
    <beanid="demoService"class="com.alibaba.dubbo.demo.provider.DemoServiceImpl"/>
 
</beans>

加载Spring配置:

Provider.java
importorg.springframework.context.support.ClassPathXmlApplicationContext;
 
publicclassProvider {
 
    publicstaticvoidmain(String[] args)throwsException {
        ClassPathXmlApplicationContext context =newClassPathXmlApplicationContext(newString[] {"http://10.20.160.198/wiki/display/dubbo/provider.xml"});
        context.start();
 
        System.in.read();// 按任意键退出
    }
 
}

服务消费者

(#)

完整安装步骤,请参见:示例消费者安装 (+)

通过Spring配置引用远程服务:

consumer.xml
<?xmlversion="1.0"encoding="UTF-8"?>
    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 
    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:applicationname="consumer-of-helloworld-app" />
 
    <!-- 使用multicast广播注册中心暴露发现服务地址 -->
    <dubbo:registryaddress="multicast://224.5.6.7:1234"/>
 
    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:referenceid="demoService"interface="com.alibaba.dubbo.demo.DemoService"/>
 
</beans>

加载Spring配置,并调用远程服务:(也可以使用IoC注入)

Consumer.java
importorg.springframework.context.support.ClassPathXmlApplicationContext;
importcom.alibaba.dubbo.demo.DemoService;
 
publicclassConsumer {
 
    publicstaticvoidmain(String[] args)throwsException {
        ClassPathXmlApplicationContext context =newClassPathXmlApplicationContext(newString[] {"http://10.20.160.198/wiki/display/dubbo/consumer.xml"});
        context.start();
 
        DemoService demoService = (DemoService)context.getBean("demoService");// 获取远程服务代理
        String hello = demoService.sayHello("world");// 执行远程方法
 
        System.out.println( hello );// 显示调用结果
    }
 
}

依赖

(+) (#)

必需依赖

  • JDK1.5+
理论上Dubbo可以只依赖JDK,不依赖于任何三方库运行,只需配置使用JDK相关实现策略。

缺省依赖

通过mvn dependency:tree > dep.log命令分析,Dubbo缺省依赖以下三方库:

[INFO] +- com.alibaba:dubbo:jar:2.1.2:compile
[INFO] |  +- log4j:log4j:jar:1.2.16:compile
[INFO] |  +- org.javassist:javassist:jar:3.15.0-GA:compile
[INFO] |  +- org.springframework:spring:jar:2.5.6.SEC03:compile
[INFO] |  +- commons-logging:commons-logging:jar:1.1.1:compile
[INFO] |  \- org.jboss.netty:netty:jar:3.2.5.Final:compile

这里所有依赖都是换照Dubbo缺省配置选的,这些缺省值是基于稳定性和性能考虑的。

  • log4j.jar和commons-logging.jar日志输出包。
    • 可以直接去掉,dubbo本身的日志会自动切换为JDK的java.util.logging输出。
    • 但如果其它三方库比如spring.jar间接依赖commons-logging,则不能去掉。
  • javassist.jar 字节码生成。
    • 如果<dubbo:provider proxy="jdk" />或<dubbo:consumer proxy="jdk" />,以及<dubbo:application compiler="jdk" />,则不需要。
  • spring.jar 配置解析。
    • 如果用ServiceConfig和ReferenceConfig的API调用,则不需要。
  • netty.jar 网络传输。
    • 如果<dubbo:protocol server="mina"/>或<dubbo:protocol server="grizzly"/>,则换成mina.jar或grizzly.jar。
    • 如果<protocol name="rmi"/>,则不需要。

可选依赖

以下依赖,在主动配置使用相应实现策略时用到,需自行加入依赖。

  • mina: 1.1.7
  • grizzly: 2.1.4
  • httpclient: 4.1.2
  • hessian_lite: 3.2.1-fixed
  • xstream: 1.4.1
  • fastjson: 1.1.8
  • zookeeper: 3.3.3
  • jedis: 2.0.0
  • xmemcached: 1.3.6
  • jfreechart: 1.0.13
  • hessian: 4.0.7
  • jetty: 6.1.26
  • hibernate-validator: 4.2.0.Final
  • zkclient: 0.1
  • curator: 1.1.10
  • cxf: 2.6.1
  • thrift: 0.8.0

JEE:

  • servlet: 2.5
  • bsf: 3.1
  • validation-api: 1.0.0.GA
  • jcache: 0.4

成熟度

(+) (#)

功能成熟度

(#)

Feature Maturity Strength Problem Advise User
并发控制 Tested 并发控制   试用  
连接控制 Tested 连接数控制   试用  
直连提供者 Tested 点对点直连服务提供方,用于测试   测试环境使用 Alibaba
分组聚合 Tested 分组聚合返回值,用于菜单聚合等服务 特殊场景使用 可用于生产环境  
参数验证 Tested 参数验证,JSR303验证框架集成 对性能有影响 试用 LaiWang
结果缓存 Tested 结果缓存,用于加速请求   试用  
泛化引用 Stable 泛化调用,无需业务接口类进行远程调用,用于测试平台,开放网关桥接等   可用于生产环境 Alibaba
泛化实现 Stable 泛化实现,无需业务接口类实现任意接口,用于Mock平台   可用于生产环境 Alibaba
回声测试 Tested 回声测试   试用  
隐式传参 Stable 附加参数   可用于生产环境  
异步调用 Tested 不可靠异步调用   试用  
本地调用 Tested 本地调用   试用  
参数回调 Tested 参数回调 特殊场景使用 试用 Registry
事件通知 Tested 事件通知,在远程调用执行前后触发   试用  
本地存根 Stable 在客户端执行部分逻辑   可用于生产环境 Alibaba
本地伪装 Stable 伪造返回结果,可在失败时执行,或直接执行,用于服务降级 需注册中心支持 可用于生产环境 Alibaba
延迟暴露 Stable 延迟暴露服务,用于等待应用加载warmup数据,或等待spring加载完成   可用于生产环境 Alibaba
延迟连接 Tested 延迟建立连接,调用时建立   试用 Registry
粘滞连接 Tested 粘滞连接,总是向同一个提供方发起请求,除非此提供方挂掉,再切换到另一台   试用 Registry
令牌验证 Tested 令牌验证,用于服务授权 需注册中心支持 试用  
路由规则 Tested 动态决定调用关系 需注册中心支持 试用  
配置规则 Tested 动态下发配置,实现功能的开关 需注册中心支持 试用  
访问日志 Tested 访问日志,用于记录调用信息 本地存储,影响性能,受磁盘大小限制 试用  
分布式事务 Research JTA/XA三阶段提交事务 不稳定 不可用  

策略成熟度

(#)

Feature Maturity Strength Problem Advise User
Zookeeper注册中心 Stable 支持基于网络的集群方式,有广泛周边开源产品,建议使用dubbo-2.3.3以上版本(推荐使用) 依赖于Zookeeper的稳定性 可用于生产环境  
Redis注册中心 Stable 支持基于客户端双写的集群方式,性能高 要求服务器时间同步,用于检查心跳过期脏数据 可用于生产环境  
Multicast注册中心 Tested 去中心化,不需要安装注册中心 依赖于网络拓普和路由,跨机房有风险 小规模应用或开发测试环境  
Simple注册中心 Tested Dogfooding,注册中心本身也是一个标准的RPC服务 没有集群支持,可能单点故障 试用  
Feature Maturity Strength Problem Advise User
Simple监控中心 Stable 支持JFreeChart统计报表 没有集群支持,可能单点故障,但故障后不影响RPC运行 可用于生产环境  
Feature Maturity Strength Problem Advise User
Dubbo协议 Stable 采用NIO复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,性能较好(推荐使用) 在大文件传输时,单一连接会成为瓶颈 可用于生产环境 Alibaba
Rmi协议 Stable 可与原生RMI互操作,基于TCP协议 偶尔会连接失败,需重建Stub 可用于生产环境 Alibaba
Hessian协议 Stable 可与原生Hessian互操作,基于HTTP协议 需hessian.jar支持,http短连接的开销大 可用于生产环境  
Feature Maturity Strength Problem Advise User
Netty Transporter Stable JBoss的NIO框架,性能较好(推荐使用) 一次请求派发两种事件,需屏蔽无用事件 可用于生产环境 Alibaba
Mina Transporter Stable 老牌NIO框架,稳定 待发送消息队列派发不及时,大压力下,会出现FullGC 可用于生产环境 Alibaba
Grizzly Transporter Tested Sun的NIO框架,应用于GlassFish服务器中 线程池不可扩展,Filter不能拦截下一Filter 试用  
Feature Maturity Strength Problem Advise User
Hessian Serialization Stable 性能较好,多语言支持(推荐使用) Hessian的各版本兼容性不好,可能和应用使用的Hessian冲突,Dubbo内嵌了hessian3.2.1的源码 可用于生产环境 Alibaba
Dubbo Serialization Tested 通过不传送POJO的类元信息,在大量POJO传输时,性能较好 当参数对象增加字段时,需外部文件声明 试用  
Json Serialization Tested 纯文本,可跨语言解析,缺省采用FastJson解析 性能较差 试用  
Java Serialization Stable Java原生支持 性能较差 可用于生产环境  
Feature Maturity Strength Problem Advise User
Javassist ProxyFactory Stable 通过字节码生成代替反射,性能比较好(推荐使用) 依赖于javassist.jar包,占用JVM的Perm内存,Perm可能要设大一些:java -XX:PermSize=128m 可用于生产环境 Alibaba
Jdk ProxyFactory Stable JDK原生支持 性能较差 可用于生产环境  
Feature Maturity Strength Problem Advise User
Failover Cluster Stable 失败自动切换,当出现失败,重试其它服务器,通常用于读操作(推荐使用) 重试会带来更长延迟 可用于生产环境 Alibaba
Failfast Cluster Stable 快速失败,只发起一次调用,失败立即报错,通常用于非幂等性的写操作 如果有机器正在重启,可能会出现调用失败 可用于生产环境 Alibaba
Failsafe Cluster Stable 失败安全,出现异常时,直接忽略,通常用于写入审计日志等操作 调用信息丢失 可用于生产环境 Monitor
Failback Cluster Tested 失败自动恢复,后台记录失败请求,定时重发,通常用于消息通知操作 不可靠,重启丢失 可用于生产环境 Registry
Forking Cluster Tested 并行调用多个服务器,只要一个成功即返回,通常用于实时性要求较高的读操作 需要浪费更多服务资源 可用于生产环境  
Broadcast Cluster Tested 广播调用所有提供者,逐个调用,任意一台报错则报错,通常用于更新提供方本地状态 速度慢,任意一台报错则报错 可用于生产环境  
Feature Maturity Strength Problem Advise User
Random LoadBalance Stable 随机,按权重设置随机概率(推荐使用) 在一个截面上碰撞的概率高,重试时,可能出现瞬间压力不均 可用于生产环境 Alibaba
RoundRobin LoadBalance Stable 轮循,按公约后的权重设置轮循比率 存在慢的机器累积请求问题,极端情况可能产生雪崩 可用于生产环境  
LeastActive LoadBalance Stable 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差,使慢的机器收到更少请求 不支持权重,在容量规划时,不能通过权重把压力导向一台机器压测容量 可用于生产环境  
ConsistentHash LoadBalance Stable 一致性Hash,相同参数的请求总是发到同一提供者,当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动 压力分摊不均 可用于生产环境  
Feature Maturity Strength Problem Advise User
条件路由规则 Stable 基于条件表达式的路由规则,功能简单易用 有些复杂多分支条件情况,规则很难描述 可用于生产环境 Alibaba
脚本路由规则 Tested 基于脚本引擎的路由规则,功能强大 没有运行沙箱,脚本能力过于强大,可能成为后门 试用  
Feature Maturity Strength Problem Advise User
Spring Container Stable 自动加载META-INF/spring目录下的所有Spring配置   可用于生产环境 Alibaba
Jetty Container Stable 启动一个内嵌Jetty,用于汇报状态 大量访问页面时,会影响服务器的线程和内存 可用于生产环境 Alibaba
Log4j Container Stable 自动配置log4j的配置,在多进程启动时,自动给日志文件按进程分目录 用户不能控制log4j的配置,不灵活 可用于生产环境 Alibaba

配置

(+) (#)

Xml配置

(+) (#)

配置项说明
详细配置项,请参见:配置参考手册 (+)
API使用说明
如果不想使用Spring配置,而希望通过API的方式进行调用,请参见:API配置 (+)
配置使用说明
想知道如何使用配置,请参见:快速启动 (+)

示例:

provider.xml
<?xmlversion="1.0"encoding="UTF-8"?>
    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 
    <dubbo:applicationname="hello-world-app" />
 
    <dubbo:registryaddress="multicast://224.5.6.7:1234"/>
 
    <dubbo:protocolname="dubbo"port="20880"/>
 
    <dubbo:serviceinterface="com.alibaba.dubbo.demo.DemoService"ref="demoServiceLocal"/>
 
    <dubbo:referenceid="demoServiceRemote"interface="com.alibaba.dubbo.demo.DemoService"/>
 
</beans>
所有标签者支持自定义参数,用于不同扩展点实现的特殊配置。

如:

<dubbo:protocolname="jms">
    <dubbo:parameterkey="queue"value="http://10.20.160.198/wiki/display/dubbo/10.20.31.22"/>
</dubbo:protocol>

或:(2.1.0开始支持)

注意声明:xmlns:p="http://www.springframework.org/schema/p"
    xsi:schemaLocation="http://www.springframework.org/schema/beans        http://www.springframework.org/schema/beans/spring-beans.xsd        http://code.alibabatech.com/schema/dubbo        http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
 
    <dubbo:protocolname="jms"p:queue="http://10.20.160.198/wiki/display/dubbo/10.20.31.22"/>
 
</beans>

Configuration Relation:

  • <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/> 用于指定方法参数配置。

Configuration Override:

  • 上图中以timeout为例,显示了配置的查找顺序,其它retries, loadbalance, actives等类似。
    • 方法级优先,接口级次之,全局配置再次之。
    • 如果级别一样,则消费方优先,提供方次之。
  • 其中,服务提供方配置,通过URL经由注册中心传递给消费方。
  • 建议由服务提供方设置超时,因为一个方法需要执行多长时间,服务提供方更清楚,如果一个消费方同时引用多个服务,就不需要关心每个服务的超时设置。
  • 理论上ReferenceConfig的非服务标识配置,在ConsumerConfig,ServiceConfig, ProviderConfig均可以缺省配置。

属性配置

(+) (#)

如果公共配置很简单,没有多注册中心,多协议等情况,或者想多个Spring容器想共享配置,可以使用dubbo.properties作为缺省配置。
Dubbo将自动加载classpath根目录下的dubbo.properties,可以通过JVM启动参数:-Ddubbo.properties.file=xxx.properties 改变缺省配置位置。
如果classpath根目录下存在多个dubbo.properties,比如多个jar包中有dubbo.properties,Dubbo会任意加载,并打印Error日志,后续可能改为抛异常。

映射规则:

  • 将XML配置的标签名,加属性名,用点分隔,多个属性拆成多行:
    • 比如:dubbo.application.name=foo等价于<dubbo:application name="foo" />
    • 比如:dubbo.registry.address=10.20.153.10:9090等价于<dubbo:registry address="10.20.153.10:9090" />
  • 如果XML有多行同名标签配置,可用id号区分,如果没有id号将对所有同名标签生效:
    • 比如:dubbo.protocol.rmi.port=1234等价于<dubbo:protocol id="rmi" name="rmi" port="1099" /> (协议的id没配时,缺省使用协议名作为id)
    • 比如:dubbo.registry.china.address=10.20.153.10:9090等价于<dubbo:registry id="china" address="10.20.153.10:9090" />

典型配置如:

dubbo.properties
dubbo.application.name=foo
dubbo.application.owner=bar
dubbo.registry.address=10.20.153.10:9090

覆盖策略:

  • JVM启动-D参数优先,这样可以使用户在部署和启动时进行参数重写,比如在启动时需改变协议的端口。
  • XML次之,如果在XML中有配置,则dubbo.properties中的相应配置项无效。
  • Properties最后,相当于缺省值,只有XML没有配置时,dubbo.properties的相应配置项才会生效,通常用于共享公共配置,比如应用名。

注解配置

(+) (#)

2.2.1以上版本支持

服务提供方注解:

importcom.alibaba.dubbo.config.annotation.Service;
 
@Service(version="1.0.0")
publicclassFooServiceImplimplementsFooService {
 
    // ......
 
}

服务提供方配置:

<!-- 公共信息,也可以用dubbo.properties配置 -->
<dubbo:applicationname="annotation-provider"/>
<dubbo:registryaddress="127.0.0.1:4548"/>
 
<!-- 扫描注解包路径,多个包用逗号分隔,不填pacakge表示扫描当前ApplicationContext中所有的类 -->
<dubbo:annotationpackage="com.foo.bar.service"/>

服务消费方注解:

importcom.alibaba.dubbo.config.annotation.Reference;
importorg.springframework.stereotype.Component;
 
@Component
publicclassBarAction {
 
    @Reference(version="1.0.0")
    privateFooService fooService;
 
}

服务消费方配置:

<!-- 公共信息,也可以用dubbo.properties配置 -->
<dubbo:applicationname="annotation-consumer"/>
<dubbo:registryaddress="127.0.0.1:4548"/>
 
<!-- 扫描注解包路径,多个包用逗号分隔,不填pacakge表示扫描当前ApplicationContext中所有的类 -->
<dubbo:annotationpackage="com.foo.bar.action"/>

也可以使用:(等价于前面的:<dubbo:annotation package="com.foo.bar.service" />)

<dubbo:annotation/>
<context:component-scanbase-package="com.foo.bar.service">
    <context:include-filtertype="annotation"expression="com.alibaba.dubbo.config.annotation.Service"/>
</context:component-scan>
Spring2.5及以后版本支持component-scan,如果用的是Spring2.0及以前版本,需配置:
<!-- Spring2.0支持@Service注解配置,但不支持package属性自动加载bean的实例,需人工定义bean的实例。-->
<dubbo:annotation/>
<beanid="barService"class="com.foo.BarServiceImpl"/>

API配置

(+) (#)

API使用范围
API仅用于OpenAPI, ESB, Test, Mock等系统集成,普通服务提供方或消费方,请采用配置方式使用Dubbo,请参见:Xml配置 (+)
API属性含义参考
API属性与配置项一对一,各属性含义,请参见:配置参考手册 (+),
比如:ApplicationConfig.setName("xxx") 对应 <dubbo:application name="xxx" />

(1) 服务提供者:

importcom.alibaba.dubbo.rpc.config.ApplicationConfig;
importcom.alibaba.dubbo.rpc.config.RegistryConfig;
importcom.alibaba.dubbo.rpc.config.ProviderConfig;
importcom.alibaba.dubbo.rpc.config.ServiceConfig;
importcom.xxx.XxxService;
importcom.xxx.XxxServiceImpl;
 
// 服务实现
XxxService xxxService =newXxxServiceImpl();
 
// 当前应用配置
ApplicationConfig application =newApplicationConfig();
application.setName("xxx");
 
// 连接注册中心配置
RegistryConfig registry =newRegistryConfig();
registry.setAddress("10.20.130.230:9090");
registry.setUsername("aaa");
registry.setPassword("bbb");
 
// 服务提供者协议配置
ProtocolConfig protocol =newProtocolConfig();
protocol.setName("dubbo");
protocol.setPort(12345);
protocol.setThreads(200);
 
// 注意:ServiceConfig为重对象,内部封装了与注册中心的连接,以及开启服务端口
 
// 服务提供者暴露服务配置
ServiceConfig<XxxService> service =newServiceConfig<XxxService>();// 此实例很重,封装了与注册中心的连接,请自行缓存,否则可能造成内存和连接泄漏
service.setApplication(application);
service.setRegistry(registry);// 多个注册中心可以用setRegistries()
service.setProtocol(protocol);// 多个协议可以用setProtocols()
service.setInterface(XxxService.class);
service.setRef(xxxService);
service.setVersion("1.0.0");
 
// 暴露及注册服务
service.export();

(2) 服务消费者:

importcom.alibaba.dubbo.rpc.config.ApplicationConfig;
importcom.alibaba.dubbo.rpc.config.RegistryConfig;
importcom.alibaba.dubbo.rpc.config.ConsumerConfig;
importcom.alibaba.dubbo.rpc.config.ReferenceConfig;
importcom.xxx.XxxService;
 
// 当前应用配置
ApplicationConfig application =newApplicationConfig();
application.setName("yyy");
 
// 连接注册中心配置
RegistryConfig registry =newRegistryConfig();
registry.setAddress("10.20.130.230:9090");
registry.setUsername("aaa");
registry.setPassword("bbb");
 
// 注意:ReferenceConfig为重对象,内部封装了与注册中心的连接,以及与服务提供方的连接
 
// 引用远程服务
ReferenceConfig<XxxService> reference =newReferenceConfig<XxxService>();// 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
reference.setApplication(application);
reference.setRegistry(registry);// 多个注册中心可以用setRegistries()
reference.setInterface(XxxService.class);
reference.setVersion("1.0.0");
 
// 和本地bean一样使用xxxService
XxxService xxxService = reference.get();// 注意:此代理对象内部封装了所有通讯细节,对象较重,请缓存复用

(3) 特殊场景

注:下面只列出不同的地方,其它参见上面的写法

(3.1) 方法级设置:

...
 
// 方法级配置
List<MethodConfig> methods =newArrayList<MethodConfig>();
MethodConfig method =newMethodConfig();
method.setName("createXxx");
method.setTimeout(10000);
method.setRetries(0);
methods.add(method);
 
// 引用远程服务
ReferenceConfig<XxxService> reference =newReferenceConfig<XxxService>();// 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
...
reference.setMethods(methods);// 设置方法级配置
 
...

(3.2) 点对点直连:

...
 
ReferenceConfig<XxxService> reference =newReferenceConfig<XxxService>();// 此实例很重,封装了与注册中心的连接以及与提供者的连接,请自行缓存,否则可能造成内存和连接泄漏
// 如果点对点直连,可以用reference.setUrl()指定目标地址,设置url后将绕过注册中心,
// 其中,协议对应provider.setProtocol()的值,端口对应provider.setPort()的值,
// 路径对应service.setPath()的值,如果未设置path,缺省path为接口名
reference.setUrl("dubbo://10.20.130.230:20880/com.xxx.XxxService");
 
...

示例

(+) (#)

想完整的运行起来,请参见:快速启动 (+),这里只列出各种场景的配置方式
以下示例全部使用基于Spring的Xml配置 (+)作为参考,如果不想使用Spring,而希望通过API的方式进行调用,请参见:API配置 (+)

启动时检查

(+) (#)

Dubbo缺省会在启动时检查依赖的服务是否可用,不可用时会抛出异常,阻止Spring初始化完成,以便上线时,能及早发现问题,默认check=true。
如果你的Spring容器是懒加载的,或者通过API编程延迟引用服务,请关闭check,否则服务临时不可用时,会抛出异常,拿到null引用,如果check=false,总是会返回引用,当服务恢复时,能自动连上。

可以通过check="false"关闭检查,比如,测试时,有些服务不关心,或者出现了循环依赖,必须有一方先启动。

关闭某个服务的启动时检查:(没有提供者时报错)

<dubbo:referenceinterface="com.foo.BarService"check="false"/>

关闭所有服务的启动时检查:(没有提供者时报错)

<dubbo:consumercheck="false"/>

关闭注册中心启动时检查:(注册订阅失败时报错)

<dubbo:registrycheck="false"/>

也可以用dubbo.properties配置:

dubbo.properties
dubbo.reference.com.foo.BarService.check=false
dubbo.reference.check=false
dubbo.consumer.check=false
dubbo.registry.check=false

也可以用-D参数:

java -Ddubbo.reference.com.foo.BarService.check=false
java -Ddubbo.reference.check=false
java -Ddubbo.consumer.check=false
java -Ddubbo.registry.check=false
注意区别
  • dubbo.reference.check=false,强制改变所有reference的check值,就算配置中有声明,也会被覆盖。
  • dubbo.consumer.check=false,是设置check的缺省值,如果配置中有显式的声明,如:<dubbo:reference check="true"/>,不会受影响。
  • dubbo.registry.check=false,前面两个都是指订阅成功,但提供者列表是否为空是否报错,如果注册订阅失败时,也允许启动,需使用此选项,将在后台定时重试。

引用缺省是延迟初始化的,只有引用被注入到其它Bean,或被getBean()获取,才会初始化。
如果需要饥饿加载,即没有人引用也立即生成动态代理,可以配置:

<dubbo:referenceinterface="com.foo.BarService"init="true"/>

集群容错

(+) (#)

在集群调用失败时,Dubbo提供了多种容错方案,缺省为failover重试。

各节点关系:

  • 这里的Invoker是Provider的一个可调用Service的抽象,Invoker封装了Provider地址及Service接口信息。
  • Directory代表多个Invoker,可以把它看成List<Invoker>,但与List不同的是,它的值可能是动态变化的,比如注册中心推送变更。
  • Cluster将Directory中的多个Invoker伪装成一个Invoker,对上层透明,伪装过程包含了容错逻辑,调用失败后,重试另一个。
  • Router负责从多个Invoker中按路由规则选出子集,比如读写分离,应用隔离等。
  • LoadBalance负责从多个Invoker中选出具体的一个用于本次调用,选的过程包含了负载均衡算法,调用失败后,需要重选。
集群容错模式:

可以自行扩展集群容错策略,参见:集群扩展

Failover Cluster
  • 失败自动切换,当出现失败,重试其它服务器。(缺省)
  • 通常用于读操作,但重试会带来更长延迟。
  • 可通过retries="2"来设置重试次数(不含第一次)。
Failfast Cluster
  • 快速失败,只发起一次调用,失败立即报错。
  • 通常用于非幂等性的写操作,比如新增记录。
Failsafe Cluster
  • 失败安全,出现异常时,直接忽略。
  • 通常用于写入审计日志等操作。
Failback Cluster
  • 失败自动恢复,后台记录失败请求,定时重发。
  • 通常用于消息通知操作。
Forking Cluster
  • 并行调用多个服务器,只要一个成功即返回。
  • 通常用于实时性要求较高的读操作,但需要浪费更多服务资源。
  • 可通过forks="2"来设置最大并行数。
Broadcast Cluster
  • 广播调用所有提供者,逐个调用,任意一台报错则报错。(2.1.0开始支持)
  • 通常用于通知所有提供者更新缓存或日志等本地资源信息。

重试次数配置如:(failover集群模式生效)

<dubbo:serviceretries="2"/>

或:

<dubbo:referenceretries="2"/>

或:

<dubbo:reference>
    <dubbo:methodname="findFoo"retries="2"/>
</dubbo:reference>

集群模式配置如:

<dubbo:servicecluster="failsafe"/>

或:

<dubbo:referencecluster="failsafe"/>

负载均衡

(+) (#)

在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为random随机调用。

可以自行扩展负载均衡策略,参见:负载均衡扩展

Random LoadBalance
  • 随机,按权重设置随机概率。
  • 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
RoundRobin LoadBalance
  • 轮循,按公约后的权重设置轮循比率。
  • 存在慢的提供者累积请求问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
LeastActive LoadBalance
  • 最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。
  • 使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。
ConsistentHash LoadBalance
  • 一致性Hash,相同参数的请求总是发到同一提供者。
  • 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。
  • 算法参见:http://en.wikipedia.org/wiki/Consistent_hashing
  • 缺省只对第一个参数Hash,如果要修改,请配置<dubbo:parameter key="hash.arguments" value="0,1" />
  • 缺省用160份虚拟节点,如果要修改,请配置<dubbo:parameter key="hash.nodes" value="320" />

配置如:

<dubbo:serviceinterface="..."loadbalance="roundrobin"/>

或:

<dubbo:referenceinterface="..."loadbalance="roundrobin"/>

或:

<dubbo:serviceinterface="...">
    <dubbo:methodname="..."loadbalance="roundrobin"/>
</dubbo:service>

或:

<dubbo:referenceinterface="...">
    <dubbo:methodname="..."loadbalance="roundrobin"/>
</dubbo:reference>

线程模型

(+) (#)

事件处理线程说明
  • 如果事件处理的逻辑能迅速完成,并且不会发起新的IO请求,比如只是在内存中记个标识,则直接在IO线程上处理更快,因为减少了线程池调度。
  • 但如果事件处理逻辑较慢,或者需要发起新的IO请求,比如需要查询数据库,则必须派发到线程池,否则IO线程阻塞,将导致不能接收其它请求。
  • 如果用IO线程处理事件,又在事件处理过程中发起新的IO请求,比如在连接事件中发起登录请求,会报“可能引发死锁”异常,但不会真死锁。
  • Dispatcher
    • all 所有消息都派发到线程池,包括请求,响应,连接事件,断开事件,心跳等。
    • direct 所有消息都不派发到线程池,全部在IO线程上直接执行。
    • message 只有请求响应消息派发到线程池,其它连接断开事件,心跳等消息,直接在IO线程上执行。
    • execution 只请求消息派发到线程池,不含响应,响应和其它连接断开事件,心跳等消息,直接在IO线程上执行。
    • connection 在IO线程上,将连接断开事件放入队列,有序逐个执行,其它消息派发到线程池。
  • ThreadPool
    • fixed 固定大小线程池,启动时建立线程,不关闭,一直持有。(缺省)
    • cached 缓存线程池,空闲一分钟自动删除,需要时重建。
    • limited 可伸缩线程池,但池中的线程数只会增长不会收缩。(为避免收缩时突然来了大流量引起的性能问题)。

配置如:

<dubbo:protocolname="dubbo"dispatcher="all"threadpool="fixed"threads="100"/>

直连提供者

(+) (#)

在开发及测试环境下,经常需要绕过注册中心,只测试指定服务提供者,这时候可能需要点对点直连,
点对点直联方式,将以服务接口为单位,忽略注册中心的提供者列表,
A接口配置点对点,不影响B接口从注册中心获取列表。

(1) 如果是线上需求需要点对点,可在<dubbo:reference>中配置url指向提供者,将绕过注册中心,多个地址用分号隔开,配置如下:(1.0.6及以上版本支持)

<dubbo:reference id="xxxService"interface="com.alibaba.xxx.XxxService"url="dubbo://localhost:20890"/>

(2) 在JVM启动参数中加入-D参数映射服务地址,如:
(key为服务名,value为服务提供者url,此配置优先级最高,1.0.15及以上版本支持)

java -Dcom.alibaba.xxx.XxxService=dubbo://localhost:20890
注意
为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。

(3) 如果服务比较多,也可以用文件映射,如:
(用-Ddubbo.resolve.file指定映射文件路径,此配置优先级高于<dubbo:reference>中的配置,1.0.15及以上版本支持)
(2.0以上版本自动加载${user.home}/dubbo-resolve.properties文件,不需要配置)

java -Ddubbo.resolve.file=xxx.properties

然后在映射文件xxx.properties中加入:
(key为服务名,value为服务提供者url)

com.alibaba.xxx.XxxService=dubbo://localhost:20890
注意
为了避免复杂化线上环境,不要在线上使用这个功能,只应在测试阶段使用。

只订阅

(+) (#)

问题
为方便开发测试,经常会在线下共用一个所有服务可用的注册中心,这时,如果一个正在开发中的服务提供者注册,可能会影响消费者不能正常运行。
解决方案
可以让服务提供者开发方,只订阅服务(开发的服务可能依赖其它服务),而不注册正在开发的服务,通过直连测试正在开发的服务。

禁用注册配置:

<dubbo:registryaddress="10.20.153.10:9090"register="false"/>

或者:

<dubbo:registryaddress="10.20.153.10:9090?register=false"/>

只注册

(+) (#)

问题
如果有两个镜像环境,两个注册中心,有一个服务只在其中一个注册中心有部署,另一个注册中心还没来得及部署,而两个注册中心的其它应用都需要依赖此服务,所以需要将服务同时注册到两个注册中心,但却不能让此服务同时依赖两个注册中心的其它服务。
解决方案
可以让服务提供者方,只注册服务到另一注册中心,而不从另一注册中心订阅服务。

禁用订阅配置:

<dubbo:registryid="hzRegistry"address="10.20.153.10:9090"/>
<dubbo:registryid="qdRegistry"address="10.20.141.150:9090"subscribe="false"/>

或者:

<dubbo:registryid="hzRegistry"address="10.20.153.10:9090"/>
<dubbo:registryid="qdRegistry"address="10.20.141.150:9090?subscribe=false"/>

静态服务

(+) (#)

有时候希望人工管理服务提供者的上线和下线,此时需将注册中心标识为非动态管理模式。
<dubbo:registryaddress="10.20.141.150:9090"dynamic="false"/>

或者:

<dubbo:registryaddress="10.20.141.150:9090?dynamic=false"/>

服务提供者初次注册时为禁用状态,需人工启用,断线时,将不会被自动删除,需人工禁用。

如果是一个第三方独立提供者,比如memcached等,可以直接向注册中心写入提供者地址信息,消费者正常使用:
(通常由脚本监控中心页面等调用)

RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
registry.register(URL.valueOf("memcached://10.20.153.11/com.foo.BarService?category=providers&dynamic=false&application=foo"));

多协议

(+) (#)

可以自行扩展协议,参见:协议扩展

(1) 不同服务不同协议

比如:不同服务在性能上适用不同协议进行传输,比如大数据用短连接协议,小数据大并发用长连接协议。

consumer.xml
<?xmlversion="1.0"encoding="UTF-8"?>
 
    <dubbo:applicationname="world" />
    <dubbo:registryid="registry"address="10.20.141.150:9090"username="admin"password="hello1234"/>
 
    <!-- 多协议配置 -->
    <dubbo:protocolname="dubbo"port="20880"/>
    <dubbo:protocolname="rmi"port="1099"/>
 
    <!-- 使用dubbo协议暴露服务 -->
    <dubbo:serviceinterface="com.alibaba.hello.api.HelloService"version="1.0.0"ref="helloService"protocol="dubbo"/>
    <!-- 使用rmi协议暴露服务 -->
    <dubbo:serviceinterface="com.alibaba.hello.api.DemoService"version="1.0.0"ref="demoService"protocol="rmi"/>
 
</beans>

(2) 多协议暴露服务

比如:需要与http客户端互操作

consumer.xml
<?xmlversion="1.0"encoding="UTF-8"?>
 
    <dubbo:applicationname="world" />
    <dubbo:registryid="registry"address="10.20.141.150:9090"username="admin"password="hello1234"/>
 
    <!-- 多协议配置 -->
    <dubbo:protocolname="dubbo"port="20880"/>
    <dubbo:protocolname="hessian"port="8080"/>
 
    <!-- 使用多个协议暴露服务 -->
    <dubbo:serviceid="helloService"interface="com.alibaba.hello.api.HelloService"version="1.0.0"protocol="dubbo,hessian"/>
 
</beans>

多注册中心

(+) (#)

可以自行扩展注册中心,参见:注册中心扩展

(1) 多注册中心注册

比如:中文站有些服务来不及在青岛部署,只在杭州部署,而青岛的其它应用需要引用此服务,就可以将服务同时注册到两个注册中心。

consumer.xml
<?xmlversion="1.0"encoding="UTF-8"?>
 
    <dubbo:applicationname="world" />
 
    <!-- 多注册中心配置 -->
    <dubbo:registryid="hangzhouRegistry"address="10.20.141.150:9090"/>
    <dubbo:registryid="qingdaoRegistry"address="10.20.141.151:9010"default="false"/>
 
    <!-- 向多个注册中心注册 -->
    <dubbo:serviceinterface="com.alibaba.hello.api.HelloService"version="1.0.0"ref="helloService"registry="hangzhouRegistry,qingdaoRegistry"/>
 
</beans>

(2) 不同服务使用不同注册中心

比如:CRM有些服务是专门为国际站设计的,有些服务是专门为中文站设计的。

consumer.xml
<?xmlversion="1.0"encoding="UTF-8"?>
 
    <dubbo:applicationname="world" />
 
    <!-- 多注册中心配置 -->
    <dubbo:registryid="chinaRegistry"address="10.20.141.150:9090"/>
    <dubbo:registryid="intlRegistry"address="10.20.154.177:9010"default="false"/>
 
    <!-- 向中文站注册中心注册 -->
    <dubbo:serviceinterface="com.alibaba.hello.api.HelloService"version="1.0.0"ref="helloService"registry="chinaRegistry"/>
 
    <!-- 向国际站注册中心注册 -->
    <dubbo:serviceinterface="com.alibaba.hello.api.DemoService"version="1.0.0"ref="demoService"registry="intlRegistry"/>
 
</beans>

(3) 多注册中心引用

比如:CRM需同时调用中文站和国际站的PC2服务,PC2在中文站和国际站均有部署,接口及版本号都一样,但连的数据库不一样。

consumer.xml
<?xmlversion="1.0"encoding="UTF-8"?>
 
    <dubbo:applicationname="world" />
 
    <!-- 多注册中心配置 -->
    <dubbo:registryid="chinaRegistry"address="10.20.141.150:9090"/>
    <dubbo:registryid="intlRegistry"address="10.20.154.177:9010"default="false"/>
 
    <!-- 引用中文站服务 -->
    <dubbo:referenceid="chinaHelloService"interface="com.alibaba.hello.api.HelloService"version="1.0.0"registry="chinaRegistry"/>
 
    <!-- 引用国际站站服务 -->
    <dubbo:referenceid="intlHelloService"interface="com.alibaba.hello.api.HelloService"version="1.0.0"registry="intlRegistry"/>
 
</beans>

如果只是测试环境临时需要连接两个不同注册中心,使用竖号分隔多个不同注册中心地址:

consumer.xml
<?xmlversion="1.0"encoding="UTF-8"?>
 
    <dubbo:applicationname="world" />
 
    <!-- 多注册中心配置,竖号分隔表示同时连接多个不同注册中心,同一注册中心的多个集群地址用逗号分隔 -->