文章目录
- 1. 什么是Dubbo
- 2. Dubbo架构
- 3. SpringBoot整合Dubbo框架
- 3.1 前期准备
- 3.1.1 Zookeeper的安装
- 3.2 项目创建
- 3.3 添加依赖
- 3.4 定义服务接口
- 3.5 服务端的实现
- 3.6 消费端请求任务
- 3.7 服务端配置文件
- 3.8 消费端配置文件
- 3.9 启动应用
- 4. Dubbo负载均衡
- 5. Dubbo集群容错
1. 什么是Dubbo
Dubbo是一款高性能、轻量级的RPC服务开发框架,是由阿里巴巴公司开源并贡献给Apache基金会的。他可以通过RPC快速调用远程服务,并且提供了很多功能,例如负载均衡、服务注册和发现、容错机制等,使得分布式服务的开发变得更加简单和方便。
RPC:Remote Procedure Call Protocol,远程过程调用协议。
2. Dubbo架构
架构图如图
角色说明
Registry:服务注册与发现的注册中心
Consumer:调用远程服务的服务消费者
Provider:暴露服务的服务提供者
Container:服务器运行容器
Monitor:统计服务的调用次数和调用时间的监控中心
调用关系说明
- 服务器运行容器启动运行服务提供者;
- 服务提供者启动时,向注册中心注册自己提供的服务;
- 服务消费者启动时,向注册中心订阅自己所需的服务;
- 注册中心返回服务提供者列表给服务消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者;
- 服务消费者从服务提供者列表中,基于负载均衡选择一个服务提供者进行调用,如果调用失败,再选择另一个;
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时发送一次统计数据到监控中心。
3. SpringBoot整合Dubbo框架
3.1 前期准备
3.1.1 Zookeeper的安装
这里注册中心使用的Zookeeper。
下载地址 https://dlcdn.apache.org/zookeeper/zookeeper-3.8.1/apache-zookeeper-3.8.1-bin.tar.gz
下载之后解压到文件夹下,这里需要将文件conf下的zoo_sample.cfg
文件改为zoo.cfg
文件,然后更改一些配置信息。
tickTime=2000
initLimit=10
syncLimit=5
dataDir=E:/apache-zookeeper-3.8.1-bin/data
clientPort=2181
admin.serverPort=2182
然后在bin目录下,点击zkServer.cmd
启动zookeeper
3.2 项目创建
先创建一个基础项目
现在还需要创建三个子模块
dubbo-api
:共享 API 模块
dubbo-consumer
:消费端模块
dubbo-provider
:服务端模块
3.3 添加依赖
在父项目的pom.xml中添加依赖
<properties>
<java.version>1.8</java.version>
<dubbo.version>3.1.0</dubbo.version>
<spring-boot.version>2.7.12</spring-boot.version>
</properties>
<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>
<!-- Dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-bom</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<version>${dubbo.version}</version>
<type>pom</type>
</dependency>
</dependencies>
</dependencyManagement>
为子项目consumer和provider两个模块添加依赖
<parent>
<groupId>com.example</groupId>
<artifactId>springboot-dubbo-demo</artifactId>
<version>0.0.1-SNAPSHOT</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.example</groupId>
<artifactId>dubbo-api</artifactId>
<version>0.0.1-SNAPSHOT</version>
</dependency>
<!-- dubbo -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-dependencies-zookeeper-curator5</artifactId>
<type>pom</type>
<exclusions>
<exclusion>
<artifactId>slf4j-reload4j</artifactId>
<groupId>org.slf4j</groupId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
3.4 定义服务接口
public interface DemoService {
String sayHello(String name);
}
3.5 服务端的实现
注意这里的Service是DubboService
@DubboService
public class DemoServiceImpl implements DemoService {
@Override
public String sayHello(String name) {
return "Hello " + name;
}
}
3.6 消费端请求任务
注意这里的@DubboReference 从 Dubbo 获取了一个 RPC 订阅。
@Component
public class Task implements CommandLineRunner {
@DubboReference
private DemoService demoService;
@Override
public void run(String... args) throws Exception {
String result = demoService.sayHello("world");
System.out.println("Receive result ======> " + result);
new Thread(()-> {
while (true) {
try {
Thread.sleep(1000);
System.out.println(new Date() + " Receive result ======> " + demoService.sayHello("world"));
} catch (InterruptedException e) {
e.printStackTrace();
Thread.currentThread().interrupt();
}
}
}).start();
}
}
3.7 服务端配置文件
dubbo:
# Dubbo 的应用名
application:
name: dubbo--provider
# Dubbo 协议信息
protocol:
name: dubbo
port: -1
# Dubbo 使用的注册中心地址
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
server:
port: 8081
3.8 消费端配置文件
dubbo:
# Dubbo 的应用名
application:
name: dubbo-consumer
# Dubbo 协议信息
protocol:
name: dubbo
port: -1
# Dubbo 使用的注册中心地址
registry:
address: zookeeper://${zookeeper.address:127.0.0.1}:2181
server:
port: 8082
3.9 启动应用
首先启动provider的启动类
这里最后日志是 [Dubbo] Current Spring Boot Application is await...
就代表成功了
然后启动consumer的启动类
4. Dubbo负载均衡
Dubbo框架提供了多种负载均衡策略,用于消费者在调用服务提供者时选择一个合适的节点进行调用。以下是Dubbo支持的几种负载均衡策略:
- 权重随机负载均衡(Random LoadBalance):随机从可用的节点中选择一个进行调用。
- 加权轮询负载均衡(Round Robin LoadBalance):按照轮询的方式依次选择可用节点进行调用。
- 最少活跃数负载均衡(Least Active LoadBalance):选择最少活跃数的节点进行调用,可以有效地避免出现单节点负载过高的情况。
- 一致性哈希负载均衡(Consistent Hash LoadBalance):将请求的关键字映射到一个哈希环上,每个节点在哈希环上占据一个位置,通过哈希算法来选择一个最近的节点进行调用。
Dubbo框架默认使用的是基于权重随机负载均衡策略。
在Spring Boot中,我们可以通过在application.properties或application.yml配置文件中指定Dubbo的负载均衡策略。具体步骤如下:
- 在application.properties或application.yml文件中添加以下配置:
# 指定负载均衡策略为轮询
dubbo.consumer.loadbalance=roundrobin
其中,dubbo.consumer.loadbalance
表示服务消费者端的负载均衡策略。
- 如果需要动态切换Dubbo的负载均衡策略,可以使用Dubbo提供的API,修改ReferenceConfig对象的负载均衡策略属性,示例代码如下:
@Autowired
private ReferenceConfig<MyService> reference;
public void changeLoadBalance(String loadBalance) {
reference.setLoadbalance(loadBalance);
}
在上面的代码中,我们注入了一个ReferenceConfig
实例,并定义了一个changeLoadBalance
方法用于动态修改负载均衡策略。调用setLoadbalance
方法修改负载均衡策略即可。
除了在application.properties或application.yml文件中配置外,我们也可以在Java Config类中通过@Bean注解自定义Dubbo的负载均衡策略,示例如下:
@Configuration
public class DubboConfig {
@Bean
public ReferenceConfig<MyService> referenceConfig() {
ReferenceConfig<MyService> reference = new ReferenceConfig<>();
reference.setInterface(MyService.class);
LoadBalance loadBalance = ExtensionLoader.getExtensionLoader(LoadBalance.class).getExtension("leastactive");
reference.setLoadbalance(loadBalance);
return reference;
}
}
在上面的代码中,我们使用@Bean注解定义了一个ReferenceConfig
实例,并通过getExtension
方法获取了Dubbo的负载均衡策略扩展实现。
5. Dubbo集群容错
Dubbo的集群容错可以提高系统的可用性和稳定性,有效地降低了服务调用失败的风险。如果服务调用出现异常或者超时,Dubbo会根据预定义的容错机制对请求进行处理,从而保证服务调用的可靠性。
Dubbo提供了多种集群容错方案,主要包括以下几种:
- Failover Cluster:这是Dubbo默认的容错机制,当请求失败时,会自动切换到另一个节点进行重试,默认情况下重试2次。可以通过设置retries属性来调整重试次数。
- Failfast Cluster:该集群容错机制非常快速,但不会进行重试。如果一个节点出现异常,那么立即返回错误响应。
- Failsafe Cluster:该集群容错机制会在出现异常时返回一个空结果,不会抛出异常。适用于有些场景下,部分节点不可用但是不影响整体服务的情况。
- Failback Cluster:该集群容错机制在发生失败后进行后台重试,不会阻塞当前请求线程。该机制可能会引起重复执行问题,需要开发者自行处理。
- Forking Cluster:该集群容错机制会同时向多个节点发起请求,并取最先返回的一个结果。可以通过设置forks属性来指定并发请求数量。
- Broadcast Cluster:将请求广播给所有提供者,适用于通知所有提供者更新缓存等操作。
在Spring Boot中,我们可以通过在application.properties或application.yml配置文件中指定Dubbo的集群容错策略。具体步骤如下:
- 在application.properties或application.yml文件中添加以下配置:
# 指定集群容错策略为Failfast Cluster
dubbo.consumer.cluster=failfast
其中,dubbo.consumer.cluster
表示服务消费者端的集群容错策略。
- 如果需要动态切换Dubbo的集群容错策略,可以使用Dubbo提供的API,修改ReferenceConfig对象的负载均衡策略属性,示例代码如下:
@Autowired
private ReferenceConfig<MyService> reference;
public void changeCluster(String cluster) {
reference.setCluster(cluster);
}
在上面的代码中,我们注入了一个ReferenceConfig
实例,并定义了一个changeCluster
方法用于动态修改集群容错策略。调用setCluster
方法修改集群容错策略即可。
除了在application.properties或application.yml文件中配置外,我们也可以在Java Config类中通过@Bean注解自定义Dubbo的集群容错策略,示例如下:
@Configuration
public class DubboConfig {
@Bean
public ReferenceConfig<MyService> referenceConfig() {
ReferenceConfig<MyService> reference = new ReferenceConfig<>();
reference.setInterface(MyService.class);
Cluster cluster = ExtensionLoader.getExtensionLoader(Cluster.class).getExtension("failover");
reference.setCluster(cluster);
return reference;
}
}
在上面的代码中,我们使用@Bean注解定义了一个ReferenceConfig
实例,并通过getExtension
方法获取了Dubbo的集群容错策略扩展实现。