SpringBoot+Dubbo+Zookeeper实现分布式系统
-
- 一、分布式系统通俗解释
- 二、环境准备(详细版)
-
- [1. 软件版本](#1. 软件版本)
- [2. 安装Zookeeper(单机模式)](#2. 安装Zookeeper(单机模式))
- 三、完整项目结构(带详细注释)
- 四、手把手代码实现
- 五、运行流程详解
-
- [1. 启动顺序](#1. 启动顺序)
- [2. 验证步骤](#2. 验证步骤)
- [3. 查看服务注册情况](#3. 查看服务注册情况)
- 六、核心机制详解
-
- [1. 服务注册过程](#1. 服务注册过程)
- [2. 服务发现过程](#2. 服务发现过程)
- [3. 通信协议](#3. 通信协议)
- 七、常见问题解决方案
-
- [1. 服务无法注册](#1. 服务无法注册)
- [2. 调用超时](#2. 调用超时)
- [3. 接口包路径不一致](#3. 接口包路径不一致)
- 八、扩展实践建议
一、分布式系统通俗解释
场景比喻:想象一个大型超市(分布式系统):
- 收银台(服务消费者):处理顾客请求
- 仓库(服务提供者):提供商品
- 总控室(Zookeeper):记录哪个仓库有什么商品
- 物流系统(Dubbo):负责收银台和仓库之间的通信
当顾客要买可乐时:
- 收银台询问总控室:哪里能拿到可乐?
- 总控室返回仓库A的地址
- 收银台通过物流系统向仓库A请求可乐
- 仓库A将可乐送到收银台
二、环境准备(详细版)
1. 软件版本
- JDK 8
- Maven 3.6.3
- Zookeeper 3.7.0 (下载地址)
2. 安装Zookeeper(单机模式)
bash
# 解压后进入conf目录
cp zoo_sample.cfg zoo.cfg
# 修改配置(关键部分)
dataDir=/tmp/zookeeper
clientPort=2181
# 启动服务(Linux/Mac)
bin/zkServer.sh start
# Windows双击zkServer.cmd
三、完整项目结构(带详细注释)
distributed-demo
├── api # 服务接口定义
├── provider # 服务提供者
└── consumer # 服务消费者
四、手把手代码实现
步骤1:创建父工程(管理依赖)
xml
<!-- pom.xml -->
<project>
<groupId>com.example</groupId>
<artifactId>distributed-demo</artifactId>
<version>1.0</version>
<packaging>pom</packaging>
<modules>
<module>api</module>
<module>provider</module>
<module>consumer</module>
</modules>
<properties>
<dubbo.version>2.7.15</dubbo.version>
<zk.version>3.7.0</zk.version>
</properties>
<dependencies>
<!-- Dubbo核心 -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>${dubbo.version}</version>
</dependency>
<!-- Zookeeper客户端 -->
<dependency>
<groupId>org.apache.curator</groupId>
<artifactId>curator-framework</artifactId>
<version>5.1.0</version>
</dependency>
</dependencies>
</project>
步骤2:API模块(定义服务契约)
java
// api/src/main/java/com/example/api/CalculatorService.java
public interface CalculatorService {
/**
* 加法服务
* @param a 加数
* @param b 被加数
* @return 和
*/
int add(int a, int b);
}
步骤3:服务提供者(实现具体逻辑)
java
// provider/src/main/java/com/example/provider/CalculatorServiceImpl.java
@DubboService // 关键注解:声明这是Dubbo服务
public class CalculatorServiceImpl implements CalculatorService {
@Override
public int add(int a, int b) {
System.out.println("收到请求:" + a + "+" + b);
return a + b;
}
}
// provider/src/main/resources/application.properties
# 应用配置
spring.application.name=calculator-provider
server.port=8081
# Dubbo配置
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.protocol.name=dubbo
dubbo.protocol.port=20880
dubbo.scan.base-packages=com.example.provider
步骤4:服务消费者(调用远程服务)
java
// consumer/src/main/java/com/example/consumer/CalculatorController.java
@RestController
public class CalculatorController {
@DubboReference // 关键注解:引用远程服务
private CalculatorService calculatorService;
@GetMapping("/add")
public String add(@RequestParam int a, @RequestParam int b) {
return a + " + " + b + " = " + calculatorService.add(a, b);
}
}
// consumer/src/main/resources/application.properties
spring.application.name=calculator-consumer
server.port=8080
dubbo.registry.address=zookeeper://127.0.0.1:2181
dubbo.consumer.timeout=3000
步骤5:启动类配置
java
// Provider启动类
@SpringBootApplication
@EnableDubbo // 启用Dubbo功能
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
System.out.println("Provider启动成功!");
}
}
// Consumer启动类
@SpringBootApplication
@EnableDubbo
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
System.out.println("Consumer启动成功!");
}
}
五、运行流程详解
1. 启动顺序
Zookeeper Provider Consumer 2181端口监听 注册服务信息 查询服务地址 返回Provider地址 发起RPC调用 返回计算结果 Zookeeper Provider Consumer
2. 验证步骤
-
启动Zookeeper
-
启动Provider(控制台看到
Provider启动成功!
) -
启动Consumer
-
访问测试接口:
http://localhost:8080/add?a=5&b=3
应返回:
5 + 3 = 8
3. 查看服务注册情况
使用Zookeeper客户端工具(推荐PrettyZoo)连接localhost:2181,查看节点:
/dubbo/com.example.api.CalculatorService/providers
六、核心机制详解
1. 服务注册过程
- Provider启动时向Zookeeper注册自己的地址
- 注册信息包括:IP、端口、接口名称、版本等
- Zookeeper以临时节点存储这些信息
2. 服务发现过程
- Consumer启动时订阅所需服务
- Zookeeper推送Provider地址列表
- Dubbo根据负载均衡策略选择Provider
3. 通信协议
- 默认使用Dubbo协议(TCP长连接)
- 数据序列化:Hessian2二进制格式
七、常见问题解决方案
1. 服务无法注册
- 检查Zookeeper是否运行:
telnet 127.0.0.1 2181
- 查看Provider日志是否有注册异常
- 确认Dubbo版本与Zookeeper版本兼容
2. 调用超时
properties
# 在consumer的配置中添加
dubbo.consumer.timeout=5000 # 单位毫秒
3. 接口包路径不一致
必须保证接口的 全限定名 在Provider和Consumer中完全一致!
八、扩展实践建议
- 多Provider测试:启动两个Provider实例,观察负载均衡
- 服务治理:集成Dubbo Admin控制台
- 容错机制 :添加
@DubboReference(cluster = "failover")
