Dubbo 介绍

官网:http://dubbo.apache.org/zh-cn/
Github:https://github.com/apache/dubbo
2018 年 2 月 15 日,阿里巴巴的服务治理框架 dubbo 通过投票,顺利成为 Apache 基金会孵化项目。
Apache Dubbo 是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。
Dubbo 架构
Dubbo 提供三个核心功能:基于接口的远程调用、容错和负载均衡,以及服务的自动注册与发现。Dubbo 框架广泛的在阿里巴巴内部使用,以及当当、去哪儿、网易考拉、滴滴等都在使用。

节点角色说明
节点 | 角色说明 |
---|---|
Provider |
暴露服务的服务提供方 |
Consumer |
调用远程服务的服务消费方 |
Registry |
服务注册与发现的注册中心 |
Monitor |
统计服务的调用次数和调用时间的监控中心 |
Container |
服务运行容器 |
调用关系说明
-
服务容器负责启动,加载,运行服务提供者。 -
服务提供者在启动时,向注册中心注册自己提供的服务。 -
服务消费者在启动时,向注册中心订阅自己所需的服务。 -
注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。 -
服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。 -
服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
Dubbo 快速入门
我们先通过一个简单的案例让大家理解一下 Dubbo 的使用,然后基于 Spring Boot 和 Spring Cloud 环境整合 Dubbo。
Dubbo 采用全 Spring 配置方式,透明化接入应用,对应用没有任何 API 侵入,只需用 Spring 加载 Dubbo 的配置即可。
依赖
JDK 1.6 以上和 Maven 3.0 以上,采用 Maven 多模块聚合工程构建 api 模块,provider 模块以及 consumer 模块。
聚合工程
项目结构如下图,简单介绍一下:
-
dubbo-api
:服务接口 -
dubbo-provider
:依赖服务接口,具体的业务实现,服务提供者 -
dubbo-coonsumer
:依赖服务接口,远程调用服务,服务消费者

依赖关系
dubbo-parent 的 pom.xml 依赖 apache dubbo。
<dependencies>
<!-- apache dubbo 依赖 --> <dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo</artifactId> <version>2.7.4.1</version> </dependency> </dependencies>
dubbo-provider 和 dubbo-consumer 的 pom.xml 依赖 dubbo-api 服务接口。
<dependencies>
<!-- dubbo-api 依赖 --> <dependency> <groupId>org.example</groupId> <artifactId>dubbo-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> </dependencies>
定义服务接口
dubbo-api 中编写 HelloService.java
package org.example.service;
/** * Hello服务 */ public interface HelloService { String sayHello(String name); }
定义服务提供者
在 provider 模块中实现服务接口
dubbo-provider 中编写 HelloServiceImpl.java
package org.example.service.impl;
import org.example.service.HelloService; /** * 服务实现 */ public class HelloServiceImpl implements HelloService { public String sayHello(String name) { return "hello " + name; } }
配置服务提供者
dubbo-provider.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" 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="hello-world-app"/> <!-- 使用 multicast 广播注册中心暴露服务地址 --> <dubbo:registry address="multicast://224.5.6.7:1234"/> <!-- 用 dubbo 协议在 20880 端口暴露服务 --> <dubbo:protocol name="dubbo" port="20880"/> <!-- 声明需要暴露的服务接口 --> <dubbo:service interface="org.example.service.HelloService" ref="helloService"/> <!-- 和本地 bean 一样实现服务 --> <bean id="helloService" class="org.example.service.impl.HelloServiceImpl"/> </beans>
加载 Spring 配置启动服务
package org.example;
import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 发布服务 */ public class Provider { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-provider.xml"); context.start(); System.out.println("服务注册成功!"); System.in.read(); // 按任意键退出 } }
定义服务消费者
通过 Spring 配置引用远程服务
dubbo-consumer.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo" 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="consumer-of-helloworld-app" /> <!-- 使用 multicast 广播注册中心暴露发现服务地址 --> <dubbo:registry address="multicast://224.5.6.7:1234" /> <!-- 生成远程服务代理,可以和本地 bean 一样使用 helloService --> <dubbo:reference id="helloService" interface="org.example.service.HelloService" /> </beans>
加载 Spring 配置并调用远程服务
package org.example;
import org.example.service.HelloService; import org.springframework.context.support.ClassPathXmlApplicationContext; /** * 调用远程服务 */ public class Consumer { public static void main(String[] args) throws Exception { ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-consumer.xml"); context.start(); HelloService helloService = (HelloService) context.getBean("helloService"); // 获取远程服务代理 String result = helloService.sayHello("world"); // 执行远程方法 System.out.println(result); // 显示调用结果 } }
Dubbo 常用标签
-
dubbo:application
:应用程序名称 -
dubbo:registry
:连接注册中心信息(配置注册中心) -
dubbo:protocol
:服务提供者注册服务采用的协议-
Dubbo 协议,默认 -
RMI 协议 -
Hessian 协议 -
HTTP 协议 -
WebService 协议 -
Thrift 协议 -
Memcached 协议 -
Redis 协议 -
Rest 协议(RESTful) -
Grpc 协议 -
更多协议信息请参考:http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html
-
-
dubbo:service
:声明需要暴露的服务接口 -
dubbo:reference
:配置订阅的服务(生成远程服务代理)
更多配置信息请参考:http://dubbo.apache.org/zh-cn/docs/user/references/xml/introduction.html
注册中心
注册中心我们已经学习了不少,例如:ZooKeeper、Eureka、Consul、Nacos 等等,注册中心可以更高效的管理系统的服务:比如服务接口的发布、自动剔除无效的服务、自动恢复服务等。
Dubbo 支持五种注册中心:Multicast、Nacos(推荐)、ZooKeeper(推荐) 、Redis、Simple。本文重点介绍前两个,更多注册中心的信息请参考:http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html
Multicast 注册中心
Multicast 注册中心不需要启动任何中心节点,只要广播地址一样,就可以互相发现。

-
提供方启动时广播自己的地址 -
消费方启动时广播订阅请求 -
提供方收到订阅请求时,单播自己的地址给订阅者,如果设置了 unicast=false
,则广播给订阅者 -
消费方收到提供方地址时,连接该地址进行 RPC 调用。
组播受网络结构限制,只适合小规模应用或开发阶段使用。组播地址段: 224.0.0.0 - 239.255.255.255
配置
<dubbo:registry address="multicast://224.5.6.7:1234" />
或
<dubbo:registry protocol="multicast" address="224.5.6.7:1234" />
为了减少广播量,Dubbo 缺省使用单播发送提供者地址信息给消费者,如果一个机器上同时启了多个消费者进程,消费者需声明 unicast=false
,否则只会有一个消费者能收到消息。
当服务者和消费者运行在同一台机器上,消费者同样需要声明unicast=false
,否则消费者无法收到消息,导致 No provider available for the service 异常。
<dubbo:registry address="multicast://224.5.6.7:1234?unicast=false" />
或
<dubbo:registry protocol="multicast" address="224.5.6.7:1234">
<dubbo:parameter key="unicast" value="false" /> </dubbo:registry>
zookeeper 注册中心
Apache ZooKeeper 是一个开放源码的分布式应用程序协调组件,是 Hadoop 和 Hbase 的重要组件。它是一个为分布式应用提供一致性服务的软件,提供的功能包括:配置维护、域名服务、分布式同步、组服务等。适合作为 Dubbo 服务的注册中心,工业强度较高,可用于生产环境,推荐使用。
在微服务项目开发中 ZooKeeper 主要的角色是当做服务注册中心存在,我们将编写好的服务注册至 ZooKeeper 即可。

流程说明:
-
服务提供者启动时: 向 /dubbo/com.foo.BarService/providers
目录下写入自己的 URL 地址。 -
服务消费者启动时: 订阅 /dubbo/com.foo.BarService/providers
目录下的提供者 URL 地址。并向/dubbo/com.foo.BarService/consumers
目录下写入自己的 URL 地址。 -
监控中心启动时: 订阅 /dubbo/com.foo.BarService
目录下的所有提供者和消费者 URL 地址。
支持以下功能:
-
当提供者出现断电等异常停机时,注册中心能自动删除提供者信息; -
当注册中心重启时,能自动恢复注册数据,以及订阅请求; -
当会话过期时,能自动恢复注册数据,以及订阅请求; -
当设置 <dubbo:registry check="false" />
时,记录失败注册和订阅请求,后台定时重试; -
可通过 <dubbo:registry username="admin" password="1234" />
设置 zookeeper 登录信息; -
可通过 <dubbo:registry group="dubbo" />
设置 zookeeper 的根节点,不配置将使用默认的根节点; -
支持 *
号通配符<dubbo:reference group="*" version="*" />
,可订阅服务的所有分组和所有版本的提供者。
❝作为 Dubbo 的老牌黄金搭档 ZooKeeper,我们在单独讲解 Dubbo 时已经给大家分享过如何使用了,本文系 Spring Cloud Alibaba 系列文章,重点对象是 Nacos,所以 ZooKeeper 这里就不过多赘述了。
❞
Nacos 注册中心
Nacos 是 Alibaba 公司推出的开源工具,用于实现分布式系统的服务发现与配置管理。Nacos 是 Dubbo 生态系统中重要的注册中心实现,其中 dubbo-registry-nacos 则是 Dubbo 融合 Nacos 注册中心的实现,推荐使用。
Nacos 官网:https://nacos.io/zh-cn/
Github:https://github.com/alibaba/nacos
预备工作
当您将 Nacos 整合到您的 Dubbo 工程之前,请确保后台已经启动 Nacos 服务。关于 Nacos 的安装和其他详细内容可参考我之前的文章 Spring Cloud 系列之 Alibaba Nacos 注册中心。
快速上手
Dubbo 融合 Nacos 成为注册中心的操作步骤非常简单,大致步骤可分为“增加 Maven 依赖”和“配置注册中心“。
依赖
核心依赖主要是 dubbo-registry-nacos
和 nacos-client
。
<!-- https://mvnrepository.com/artifact/org.apache.dubbo/dubbo-registry-nacos -->
<dependency> <groupId>org.apache.dubbo</groupId> <artifactId>dubbo-registry-nacos</artifactId> <version>2.7.4.1</version> </dependency> <!-- https://mvnrepository.com/artifact/com.alibaba.nacos/nacos-client --> <dependency> <groupId>com.alibaba.nacos</groupId> <artifactId>nacos-client</artifactId> <version>1.3.0</version> </dependency>
配置注册中心
服务提供者和服务消费者只需要调整 address
属性配置即可。
单机配置:
<!-- 使用 Nacos 注册中心,单机版 -->
<dubbo:registry address="nacos://127.0.0.1:8848"/> <!-- 或 --> <dubbo:registry protocol="nacos" address="127.0.0.1:2181"/>
或:
dubbo.register.address=nacos://192.168.10.101:8848
或:
dubbo.register.protocol=nacos
dubbo.register.address=192.168.10.101:8848
集群配置:
<!-- 使用 Nacos 注册中心,集群版 -->
<dubbo:registry address="nacos://192.168.10.101:2181?backup=192.168.10.102:2181,192.168.10.103:2181"/> <!-- 或 --> <dubbo:registry protocol="nacos" address="192.168.10.101:2181,192.168.10.102:2181,192.168.10.103:2181"/>
或:
dubbo.register.address=nacos://192.168.10.101:8848
或:
dubbo.register.protocol=nacos
dubbo.register.address=192.168.10.101:8848,192.168.10.102:8848,192.168.10.103:8848
随后,重启您的 Dubbo 应用,Dubbo 的服务提供和消费信息在 Nacos 控制台中即可显示。
Spring Cloud Alibaba Nacos 整合 Dubbo
之前的文章中,无论我们学习 Eureka、Consul 还是 Nacos,负责服务间通信的功能都是由 Ribbon 来完成的,接下来我们使用 Dubbo 来替换 Ribbon。
聚合工程
dubbo-demo
聚合工程。SpringBoot 2.3.0.RELEASE
、Spring Cloud Hoxton.SR5
。
项目结构如下图,简单介绍一下:
-
service-api
:服务接口 -
product-service
:商品服务,服务提供者,提供了/product/list
接口 -
order-service
:订单服务,服务消费者,远程调用商品服务

依赖关系
dubbo-demo 的 pom.xml。
<?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.example</groupId> <!-- 项目模块名称 --> <artifactId>dubbo-demo</artifactId> <packaging>pom</packaging> <!-- 项目版本名称 快照版本SNAPSHOT、正式版本RELEASE --> <version>1.0-SNAPSHOT</version> <modules> <module>service-api</module> <module>product-service</module> <module>order-service</module> </modules> <!-- 继承 spring-boot-starter-parent 依赖 --> <!-- 使用继承方式,实现复用,符合继承的都可以被使用 --> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> </parent> <!-- 集中定义依赖组件版本号,但不引入, 在子工程中用到声明的依赖时,可以不加依赖的版本号, 这样可以统一管理工程中用到的依赖版本 --> <properties> <!-- Spring Cloud Hoxton.SR5 依赖 --> <spring-cloud.version>Hoxton.SR5</spring-cloud.version> <!-- spring cloud alibaba 依赖 --> <spring-cloud-alibaba.version>2.1.0.RELEASE</spring-cloud-alibaba.version> </properties> <!-- 项目依赖管理 父项目只是声明依赖,子项目需要写明需要的依赖(可以省略版本信息) --> <dependencyManagement> <dependencies> <!-- spring cloud 依赖 --> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-dependencies</artifactId> <version>${spring-cloud.version}</version> <type>pom</type> <scope>import</scope> </dependency> <!-- spring cloud alibaba 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dependencies</artifactId> <version>${spring-cloud-alibaba.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> </project>
service-api 的 pom.xml
<?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"> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>service-api</artifactId> <dependencies> <!-- lombok 依赖 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies> </project>
product-service 需要依赖 Nacos 和 Dubbo 的依赖,还有 service-api 的依赖,完整依赖如下:
<?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"> <!-- 继承父依赖 --> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>product-service</artifactId> <!-- 项目依赖 --> <dependencies> <!-- spring cloud alibaba nacos discovery 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- spring cloud alibaba dubbo 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dubbo</artifactId> </dependency> <!-- spring boot web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- service-api 依赖 --> <dependency> <groupId>com.example</groupId> <artifactId>service-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- spring boot test 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>
order-service 需要依赖 Nacos 和 Dubbo 的依赖,还有 service-api 的依赖,完整依赖如下:
<?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"> <!-- 继承父依赖 --> <parent> <artifactId>dubbo-demo</artifactId> <groupId>com.example</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>order-service</artifactId> <!-- 项目依赖 --> <dependencies> <!-- spring cloud alibaba nacos discovery 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <!-- spring cloud alibaba dubbo 依赖 --> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-dubbo</artifactId> </dependency> <!-- spring boot web 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <!-- service-api 依赖 --> <dependency> <groupId>com.example</groupId> <artifactId>service-api</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <!-- spring boot test 依赖 --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </project>
定义服务接口
我们在 service-api
模块中定义实体类和服务接口信息。
实体类
Product.java
package com.example.product.pojo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; @Data @NoArgsConstructor @AllArgsConstructor public class Product implements Serializable { private Integer id; private String productName; private Integer productNum; private Double productPrice; }
Order.java
package com.example.product.pojo;
import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.List; @Data @NoArgsConstructor @AllArgsConstructor public class Order implements Serializable { private Integer id; private String orderNo; private String orderAddress; private Double totalPrice; private List<Product> productList; }
服务接口
package com.example.product.service;
import com.example.product.pojo.Product; import java.util.List; /** * 商品服务 */ public interface ProductService { /** * 查询商品列表 * * @return */ List<Product> selectProductList(); }
定义服务提供者
配置文件
配置文件需要配置 Nacos 注册中心和 Dubbo 相关信息,核心配置如下:
server:
port: 7070 # 端口 spring: application: name: product-service # 应用名称 # 配置 Nacos 注册中心 cloud: nacos: discovery: enabled: true # 如果不想使用 Nacos 进行服务注册和发现,设置为 false 即可 server-addr: 127.0.0.1:8848 # Nacos 服务器地址,单机版 # Dubbo dubbo: # 提供方应用信息,用于计算依赖关系 application: name: product-service # 使用 nacos 注册中心暴露服务地址 registry: protocol: nacos address: spring-cloud://localhost # 用 dubbo 协议在 20880 端口暴露服务 protocol: name: dubbo port: 20880 # 扫描需要暴露的服务,可以被 @EnableDubbo 注解替代 #scan: # base-packages: com.example.service
服务提供者
product-service 的 ProductServiceImpl.java
package com.example.service.impl;
import com.example.product.pojo.Product; import com.example.product.service.ProductService; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.Service; import java.util.Arrays; import java.util.List; /** * 商品服务 * timeout 调用该服务的超时时间 * version 为版本号 * group 为分组 * interface、group、version 三者确定一个服务 */ @Slf4j @Service(timeout = 5000, version = "1.0", group = "product-service") public class ProductServiceImpl implements ProductService { /** * 查询商品列表 * * @return */ @Override public List<Product> selectProductList() { log.info("商品服务查询商品信息..."); return Arrays.asList( new Product(1, "华为手机", 1, 5800D), new Product(2, "联想笔记本", 1, 6888D), new Product(3, "小米平板", 5, 2020D) ); } }
值得注意的是 @Service
注解不是 Spring 的注解而是 Dubbo
的注释:

启动类
启动类通过 @EnableDubbo
注解扫描需要暴露的服务,如果配置文件中配置了该选项,那么这里可以省略。
package com.example;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // 扫描需要暴露的服务 @EnableDubbo(scanBasePackages = "com.example.service") // 开启 @EnableDiscoveryClient 注解,当前版本默认会开启该注解 //@EnableDiscoveryClient @SpringBootApplication public class ProductServiceApplication { public static void main(String[] args) { SpringApplication.run(ProductServiceApplication.class, args); } }
定义服务消费者
配置文件
配置文件需要配置 Nacos 注册中心和 Dubbo 相关信息,核心配置如下:
server:
port: 9090 # 端口 spring: application: name: order-service # 应用名称 # 配置 Nacos 注册中心 cloud: nacos: discovery: enabled: true # 如果不想使用 Nacos 进行服务注册和发现,设置为 false 即可 server-addr: 127.0.0.1:8848 # Nacos 服务器地址,单机版 # Dubbo dubbo: # 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 application: name: order-service # 发现 nacos 注册中心暴露的服务 registry: protocol: nacos address: spring-cloud://localhost cloud: subscribed-services: product-service # 订阅服务,远程调用的服务名称
服务消费者
order-service 的 OrderServiceImpl.java
package com.example.service.impl;
import com.example.product.pojo.Order; import com.example.product.service.ProductService; import com.example.service.OrderService; import lombok.extern.slf4j.Slf4j; import org.apache.dubbo.config.annotation.Reference; import org.springframework.stereotype.Service; @Slf4j @Service public class OrderServiceImpl implements OrderService { // dubbo 提供了 @Reference 注解,可替换 @Autowired 注解,用于引入远程服务 // 如果注册服务时设置了版本及分组信息,调用远程服务时也要设置对应的版本及分组信息 @Reference(timeout = 5000, version = "1.0", group = "product-service") private ProductService productService; /** * 根据主键查询订单 * * @param id * @return */ @Override public Order selectOrderById(Integer id) { log.info("订单服务查询订单信息..."); return new Order(id, "order-001", "中国", 22788D, productService.selectProductList()); } }
启动类
package com.example;
import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; // 开启 @EnableDiscoveryClient 注解,当前版本默认会开启该注解 //@EnableDiscoveryClient @SpringBootApplication public class OrderServiceApplication { public static void main(String[] args) { SpringApplication.run(OrderServiceApplication.class, args); } }
测试
先启动 Nacos 服务器,然后启动服务提供者 product-service,访问:http://localhost:8848/nacos/ 控制台显示如下:


然后启动服务消费者,控制台显示如下:

订单服务调用远程商品服务,结果如下:

Dubbo 负载均衡
在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random
随机调用,也可以自行扩展负载均衡策略。
负载均衡策略
Random LoadBalance
-
「随机」,按权重设置随机概率。 -
在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

RoundRobin LoadBalance
-
「轮询」,按公约后的权重设置轮询比率。 -
存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。
LeastActive LoadBalance
-
「最少活跃调用数」,ping 值(延迟低)的调用,相同延迟的情况下随机。 -
使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

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-admin)对服务动态的指定权重,官方文档:http://dubbo.apache.org/zh-cn/docs/admin/introduction.html
xml
服务端服务级别
<dubbo:service interface="..." loadbalance="roundrobin" weight="100" />
客户端服务级别
<dubbo:reference interface="..." loadbalance="roundrobin" />
服务端方法级别
<dubbo:service interface="..." weight="100">
<dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:service>
客户端方法级别
<dubbo:reference interface="...">
<dubbo:method name="..." loadbalance="roundrobin"/> </dubbo:reference>
yaml
dubbo:
provider: loadbalance: roundrobin weight: 100 consumer: loadbalance: roundrobin
注解
@Service(loadbalance = "roundrobin", weight = 100)
@Reference(loadbalance = "roundrobin")


至此 Dubbo RPC 通信所有的知识点就讲解结束了。

本文采用 知识共享「署名-非商业性使用-禁止演绎 4.0 国际」许可协议
。
大家可以通过 分类
查看更多关于 Spring Cloud
的文章。
🤗 您的点赞
和转发
是对我最大的支持。
📢 扫码关注 哈喽沃德先生
「文档 + 视频」每篇文章都配有专门视频讲解,学习更轻松噢 ~

