一、Dubbo简介
1、什么是Dubbo
Dubbo是一款高性能、高可用的、基于Java开源的RPC框架;由阿里巴巴开发并开源,
现为 Apache 顶级项目;它提供了三大核心功能,即:
(1)面向接口的远程方法调用
(2)智能容错和负载均衡
(3)服务自动注册和发现
所以 Dubbo框架不仅仅是具备RPC访问功能,还包含服务治理功能;
2、Dubbo核心架构
2.1、Dubbo架构图
Dubbo 架构图如下所示:

注:上图中虚线表示异步,实线表示同步;异步不阻塞线程性能高,同步阻塞线程必须
等待响应结果才能继续执行,相对性能低
2.2、Dubbo 架构中的角色
由上图中可以发现,在Dubbo 中主要包含 Provicer、Consumer、Registry、Container、
Monitor 等角色,下边分别对这些角色及功能进行介绍。
2.2.1、Provicer
Provicer 是服务提供者,暴露服务供消费者调用,处理消费者请求;在项目启动时,
Provicer 主动向注册中心注册自己提供的服务;另外 Provicer 主要实现具体的业务逻辑,
并定期向监控中心发送调用统计数据;
注意:
Provicer 暴露的对外提供服务的接口并不是在 Provicer 项目中定义的,该服务接口
是单独定义在一个项目中,Provicer 中对外的服务需要实现该接口,然后由Consumer
客户端调用。该服务接口在 Consumer远程调用 Provicer 过程中起到“桥梁”的作用;
2.2.2、Consumer
Consumer 是服务消费者,用于远程调用其他服务;启动时,向注册中心订阅所需的服
务,获取服务提供者的列表并缓存,通过负载均衡策略选择提供者;Consumer也会定期
向监控中心发送调用统计数据
2.2.3、Registry
Registry 是服务注册中心(提供服务注册与发现),放置所有Provider对外提供的信息。
包含Provider的IP,访问端口,访问遵守的协议,对外提供的接口,接口中有哪些方法
等相关信息;
Dubbo常用的注册中心有:Zookeeper、Nacos、Redis、Multicast、Simple
另外,客户端 Consumer 要想订阅到目标Provicer服务,则也需要注册到注册中心中,
如下图所示:
注:以zookeeper作为注册中心为例

2.2.4、Container
Container 是服务运行的容器,一般指spring容器,因为Dubbo是完全基于spring实现的;
负责启动、加载和运行服务提供者、管理服务生命周期和提供必要的运行环境支持
2.2.5、Monitor
Monitor 是监控中心,监控Provider的压力情况等。每隔2分钟Consumer和Provider会把
调用次数发送给Monitor,由Monitor进行统计
2.3、Dubbo的执行流程
以上边Dubbo架构图中的步骤顺序来看下Dubbo的执行流程。
Step 0 start :
启动容器(即spring 容器)时,会把Provicer启动,并将服务接口实现类封装为
Invoker,接着将 Invoker 转换为 Exporter;最后通过具体的 Protocol 协议将服务
暴露到网络中供Consumer调用
Step 1 register :
把Provider服务注册到Registry里,注册内容包括服务提供者地址、接口、方法等信息
Step 2 subscribe :
Consumer消费者启动时,从注册中心订阅所需服务,
Step 3 notify :
注册中心返回提供者地址列表给Consumer,Consumer缓存服务提供者Provider列表
Step 4 invoke :
Consumer消费者根据注册中心Registry提供的服务提供者信息,并通过 ProxyFactory
创建服务接口的代理对象,代理对象内部封装了远程调用逻辑,可以远程调用服务提
供者
Step 5 count:
Consumer和Provider把调用次数信息异步发送给Monitor进行统计
3、Dubbo 支持的协议介绍
3.1、Dubbo支持的协议
一般Provider需要配置Dubbo的协议,Consumer不需要配置
3.1.1、Dubbo协议(官方推荐)
优点:采用NIO复用单一长连接,并使用线程池并发处理请求,减少握手和加大并发效率,
性能较好(推荐使用)
缺点:大文件上传时,可能出现问题(不使用Dubbo文件上传)
3.1.2、RMI(Remote Method Invocation)协议
优点:JDK自带的功能,不用引入其他依赖,兼容性好,
缺点:偶尔连接失败
3.1.3、Hessian协议
优点:可与原生Hessian互操作,基于HTTP协议
缺点:需hessian.jar支持,http短连接的开销大
二、第一个Dubbo练习示例
1、创建父工程dubbo-demo,dubbo-demo包含3个子模块,分别是api(定义服务接口)、
provider(服务提供者)和consumer(消费者);因为 provider和consumer都要引入
api 模块,所以我们把公用的dubbo依赖放在api模块中,

导入dubbo依赖如下:
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- curator-recipes -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-recipes</artifactId>
</dependency>
<!-- curator-framework -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
</dependency>
2、api 模块
api 中只用来定义Provider 的对外服务接口,其他什么也不干,也不需要启动;
Provider 的对外提供的服务需要实现api 中相关的接口;consumer中需要api的接口来实现远
程调用;所以 provider和consumer都要引入api模块。
示例代码如下所示:

/****************************************************
* API 在Dubbo,更像是 服务端Provider与客户端Consumer 中间的桥梁,
* 在API 中定义 Provider 对外暴露服务的接口,该接口由 Provider 实现,并使用
* Dubbo 注解 @DubboService 标识该接口的实现类是Provider暴露的服务;
* 该接口由Consumer 客户端调用
*
* @author
* @date 2025/6/4 15:39
****************************************************/
public interface DubboDemoService {
String demo(String name);
}
3、provider 模块
1)定义对外提供的服务,该服务需要实现api中定义的服务接口并使用Dubbo中的注解
@DubboService 标识该类是一个Dubbo服务,示例代码如下:
import com.msb.dubbo.api.service.DubboDemoService;
import org.apache.dubbo.config.annotation.DubboService;
/****************************************************
* todo: 注意:
* 1)该类需要加上 注解@DubboService(或apache dubbo 包下的@Service) ,标识该类是一个Dubbo服务,
* 才能被注册,
* 2)该类需要实现API 端定义的接口
*
* @author
* @date 2025/6/4 15:50
****************************************************/
@DubboService
public class DubboDemoServiceImpl implements DubboDemoService {
@Override
public String demo(String name) {
return name+" hello Dubbo test!";
}
}
2)在启动类上添加注解 @EnableDubbo 开启dubbo应用,示例代码如下:
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/****************************************************
* dubbo 使用步骤:
* 1、定义api接口模块,如: api;在客户端模块定义对外接口
* 2、定义服务端Provider,如:provider,服务端需要引入客户端依赖,
* 3、在服务端定义Dubbo服务,并实现客户端定义的对外接口
* 4、在服务端开启Dubbo,如在启动类上加上注解 @EnableDubbo
* 5、Consumer 客户端通过 api中的接口实现远程调用
*
* @author
* @date 2025/6/4 15:44
****************************************************/
@EnableDubbo //启用dubbo
@SpringBootApplication
public class DubboProviderApplication {
public static void main(String[] args) {
SpringApplication.run(DubboProviderApplication.class);
}
}
3)配置Dubbo 信息
provider 需要配置protocol 协议信息,而consumer客户端不需要该项配置
配置信息如下:
dubbo:
application:
#dubbo注册到服务中心的服务名称
name: dubbo-provider
registry:
#dubbo注册中心地址,zookeeper表示这里以zookeeper作为注册中心
address: zookeeper://47.117.80.49:2181
#配置dubbo连接zookeeper的超时时间
timeout: 10000
#配置dubbo 协议端口号
protocol:
port: 20884
#注意:此属性有默认值,但还需要手动指定,否则有可能报错
name: dubbo
4、consumer 模块
consumer 是远程服务的调用者,在 consumer 中通过api中定义的服务接口来执行远程调用
,有一点需要注意,注入 api 提供的服务接口时需要使用注解 @DubboReference。
步骤如下:
1)定义正常的service服务,该服务正常使用spring提供的@Service 注解,或spring提供的
其他注解,但 注入 api 提供的服务接口时需要使用Dubbo提供的解 @DubboReference
示例代码如下:
/****************************************************
*
* @author
* @date 2025/6/4 16:24
****************************************************/
public interface DubboDemoService {
public String demo();
}
/****************************************************
*
* @author
* @date 2025/6/4 16:26
****************************************************/
@Service
public class DubboDemoServiceImpl implements DubboDemoService {
/**
* 标识从dubbo 注册中心获取服务,即通过dubbo 实现客户端 Consumer调用服务端Provider的接口;
* 在这个过程中 api模块起到一个桥梁作用
*/
@DubboReference
private com.msb.dubbo.api.service.DubboDemoService dubboDemoService;
@Override
public String demo() {
return dubboDemoService.demo("张三丰");
}
/****************************************************
*
* @author
* @date 2025/6/4 16:29
****************************************************/
@RestController
public class DubboDemoController {
@Autowired
private DubboDemoService dubboDemoService;
@RequestMapping("/test")
public String test(){
return dubboDemoService.demo();
}
}
2)在启动类上添加注解 @EnableDubbo 开启dubbo应用,示例代码如下:
/****************************************************
*
* @author
* @date 2025/6/4 16:23
****************************************************/
@EnableDubbo
@SpringBootApplication
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class);
}
}
3)配置Dubbo 信息
server:
port: 8003
#配置dubbo
dubbo:
application:
#配置服务名称,在dubbo中的服务名称
name: dubbo-consumer
registry:
#配置注册中心地址,这里用zookeeper作为dubbo注册中心
address: zookeeper://47.117.80.49:2181
timeout: 10000
三、Dubbo支持的负载均衡
Dubbo 内部提供了4中负载均衡策略,分别是

1)Random LoadBalance(随机负载均衡)
随机选择一个服务提供者进行调用,访问概率与权重有关。
在Dubbo服务上的注解@DubboService 的属性 weight 来指定服务的权重,如下图:

适用于服务提供者数量不多的情况,或者对服务调用的顺序没有严格要求时。
2)RoundRobin LoadBalance(轮询负载均衡)
按顺序轮流选择服务提供者进行调用,访问频率与权重有关。
适用于请求均匀分配到每个服务提供者,保证每个服务提供者都能被平均调用。
3)LeastActive LoadBalance(最少活跃调用数负载均衡)
根据服务提供者的当前活跃调用数选择一个服务提供者进行调用,活跃调用数越
少,被选中的概率越大。
适用于处理请求速度差异较大的服务提供者,能够优先选择较空闲的服务提供者。
4)ConsistentHash LoadBalance(一致性Hash负载均衡)
根据请求的参数(如URL的某个部分或特定的参数)进行hash,然后根据hash结果
选择一个服务提供者。
适用于需要保证相同参数的请求总是路由到同一服务提供者的场景,比如缓存数据
的一致性需求。
Dubbo 负载均衡使用很简单,只需要在客户Consumer在调用Dubbo 服务时,在Dubbo 注解
@DubboReference 中使用属性 loadbalance 来指定负载均衡模式,如下图所示:



2538

被折叠的 条评论
为什么被折叠?



