SpringBoot 集成 Dubbo
分布式、微服务与 RPC
什么是分布式?分布式就是将一个应用程序的功能拆分到多个独立的进程中,每个进程都运行在不同的机器上,通过网络连接起来,这样就形成了一个分布式的系统。
什么是微服务架构?微服务架构将应用程序拆分成一组小的服务(微服务),每个服务运行在自己的进程中,服务之间通过轻量级的通信机制互相通信。
什么是 RPC?RPC(Remote Procedure Call)远程过程调用,微服务架构中,服务与服务之间通过网络通信的过程。比如 A 服务调用 B 服务中的方法的过程,就叫 RPC。
什么是 Dubbo
Dubbo 是一款高性能、轻量级的开源 Java RPC 框架。主要解决了微服务之间的通信问题,它提供了一套类似于本地调用的远程调用方式。
Dubbo 架构
角色说明:
- 服务提供者(Provider):服务提供者就是实现了服务接口的类。服务提供者启动时,向注册中心注册自己提供的服务。
- 服务消费者(Consumer):服务消费者就是调用远程服务的类。服务消费者启动时,向注册中心订阅自己所需的服务。
- 注册中心(Registry):注册中心存储服务提供者的地址信息。服务提供者的地址发生变化时,注册中心更新服务提供者地址信息,并通知服务消费者。Dubbo 官方推荐使用 ZooKeeper 作为注册中心。
- 监控中心(Monitor):监控中心主要用于监控服务的运行状态,以便出现问题时,能及时发现和解决。
- 容器(Container):服务运行容器,一般就是 Spring 容器。
交互过程说明:
- 虚线都是异步访问,实线都是同步访问
- 蓝色虚线:在启动时完成的功能
- 红色虚线(实线)都是程序运行过程中执行的功能
调用关系说明:
- 服务容器负责启动,加载,运行服务提供者。
- 服务提供者在启动时,向注册中心注册自己提供的服务。
- 服务消费者在启动时,向注册中心订阅自己所需的服务。
- 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。
- 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。
- 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。
示例
安装并启动 Zookeeper
我们用 Zookeeper 作为注册中心,所以先安装并启动 Zookeeper。
安装 Zookeeper:
- 安装 JDK(略)
- 把 Zookeeper 的压缩包(这里是 zookeeper-3.4.6.tar.gz)上传到 Linux
- 解压缩压缩包:
tar -zxvf zookeeper-3.4.6.tar.gz
,假设解压到/usr/local/zookeeper-3.4.6
- 进入 zookeeper-3.4.6 目录,创建 data 目录:
mkdir data
- 进入 conf 目录,把 zoo_sample.cfg 改名为 zoo.cfg:
mv zoo_sample.cfg zoo.cfg
- 打开 zoo.cfg 文件,修改 dataDir 属性:
dataDir=/usr/local/zookeeper-3.4.6/data
进入 Zookeeper 的 bin 目录,可管理 Zookeeper 服务:
- 启动服务:
./zkServer.sh start
- 停止服务:
./zkServer.sh stop
- 查看服务状态:
./zkServer.sh status
运行./zkServer.sh start
将其启动。
项目结构
下面是示例工程的项目结构。包含父工程dubbo
,接口模块dubbo-api
、服务消费者模块dubbo-consumer
和服务提供者模块dubbo-provider
。
dubbo # 父工程 ├─ dubbo-api # 接口模块 │ ├─ src │ │ └─ main │ │ └─ java │ │ └─ com │ │ └─ ming │ │ └─ api │ │ └─ service │ │ └─ HelloService.java │ └─ pom.xml ├─ dubbo-consumer # 服务消费者模块 │ ├─ src │ │ └─ main │ │ ├─ java │ │ │ └─ org │ │ │ └─ ming │ │ │ └─ consumer │ │ │ ├─ controller │ │ │ │ └─ HelloController.java │ │ │ └─ DubboConsumerApplication.java │ │ └─ resources │ │ └─ application.yml │ └─ pom.xml ├─ dubbo-provider # 服务提供者模块 │ ├─ src │ │ └─ main │ │ ├─ java │ │ │ └─ org │ │ │ └─ ming │ │ │ └─ provider │ │ │ ├─ service │ │ │ │ └─ HelloServiceImpl.java │ │ │ └─ DubboProviderApplication.java │ │ └─ resources │ │ └─ application.yml │ └─ pom.xml └─ pom.xml
父工程
父工程仅包含一个 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>org.ming</groupId> <artifactId>dubbo</artifactId> <version>1.0-SNAPSHOT</version> <packaging>pom</packaging> <modules> <module>dubbo-api</module> </modules> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <dubbo.version>2.0.0</dubbo.version> <dubbo.api.version>1.0-SNAPSHOT</dubbo.api.version> <zkclient.version>0.11</zkclient.version> </properties> <dependencies> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <version>1.18.28</version> </dependency> </dependencies> </project>
接口模块
接口模块包含一个接口和一个 pom.xml 文件。
接口模块的作用是给出 API,在服务提供者与服务消费者之间建立契约。后面会看到,服务提供者会实现接口模块中的接口,服务消费者会调用对应接口中的方法。
package com.ming.api.service; /** * Hello 服务接口 */ public interface HelloService { /** * 问好 * * @param name 姓名 * @return 问好 */ String sayHello(String name); }
<?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> <parent> <groupId>org.ming</groupId> <artifactId>dubbo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>dubbo-api</artifactId> <properties> <maven.compiler.source>8</maven.compiler.source> <maven.compiler.target>8</maven.compiler.target> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> </project>
服务提供者模块
服务提供者模块包含服务实现类、application.yml 和 pom.xml 文件。
服务实现类中使用了@Service
注解,该注解用于标注一个类为一个 Dubbo 服务。
application.yml 中配置了 Zookeeper 地址,pom.xml 中引入了 dubbo、Zookeeper 相关依赖和dubbo-api
。
package org.ming.provider.service; import com.alibaba.dubbo.config.annotation.Service; import com.ming.api.service.HelloService; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; /** * Hello 服务实现 */ @Service @Component @Slf4j public class HelloServiceImpl implements HelloService { /** * 问好 * * @param name 姓名 * @return 问好 */ @Override public String sayHello(String name) { log.info("someone is calling me......"); return "say hello to: " + name; } }
server: port: 9090 spring: dubbo: application: name: spring-boot-demo-dubbo-provider registry: zookeeper://localhost:2181
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.ming</groupId> <artifactId>dubbo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>dubbo-provider</artifactId> <version>0.0.1-SNAPSHOT</version> <name>dubbo-provider</name> <description>dubbo-provider</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.6.13</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>${dubbo.version}</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>${zkclient.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>dubbo-api</artifactId> <version>${dubbo.api.version}</version> <scope>compile</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <mainClass>org.ming.provider.DubboProviderApplication</mainClass> <skip>true</skip> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
服务消费者模块
服务消费者模块包含控制器类、application.yml 和 pom.xml 文件。
控制器类中使用了@Reference
注解,该注解用于将服务提供者的接口实现注入到控制器类中。
application.yml 中配置了 Zookeeper 地址,pom.xml 中引入了 dubbo、Zookeeper 相关依赖和dubbo-api
。
package org.ming.consumer.controller; import com.alibaba.dubbo.config.annotation.Reference; import com.ming.api.service.HelloService; import lombok.extern.slf4j.Slf4j; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; /** * Hello 服务 API */ @RestController @Slf4j public class HelloController { @Reference private HelloService helloService; @GetMapping("/sayHello") public String sayHello(@RequestParam(defaultValue = "ming") String name) { log.info("i'm ready to call someone......"); return helloService.sayHello(name); } }
server: port: 8080 spring: dubbo: application: name: spring-boot-demo-dubbo-consumer registry: zookeeper://localhost:2181
<?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 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.ming</groupId> <artifactId>dubbo</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>dubbo-consumer</artifactId> <version>0.0.1-SNAPSHOT</version> <name>dubbo-consumer</name> <description>dubbo-consumer</description> <properties> <java.version>1.8</java.version> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <spring-boot.version>2.6.13</spring-boot.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.alibaba.spring.boot</groupId> <artifactId>dubbo-spring-boot-starter</artifactId> <version>${dubbo.version}</version> </dependency> <dependency> <groupId>com.101tec</groupId> <artifactId>zkclient</artifactId> <version>${zkclient.version}</version> </dependency> <dependency> <groupId>${project.groupId}</groupId> <artifactId>dubbo-api</artifactId> <version>${dubbo.api.version}</version> <scope>compile</scope> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-dependencies</artifactId> <version>${spring-boot.version}</version> <type>pom</type> <scope>import</scope> </dependency> </dependencies> </dependencyManagement> <build> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <configuration> <source>1.8</source> <target>1.8</target> <encoding>UTF-8</encoding> </configuration> </plugin> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> <version>${spring-boot.version}</version> <configuration> <mainClass>org.ming.consumer.DubboConsumerApplication</mainClass> <skip>true</skip> </configuration> <executions> <execution> <id>repackage</id> <goals> <goal>repackage</goal> </goals> </execution> </executions> </plugin> </plugins> </build> </project>
启动服务并测试
启动服务提供者、服务消费者模块,访问 http://localhost:8080/sayHello?name=ming,收到如下响应说明成功:
say hello to: ming
参考:
spring-boot-demo/demo-dubbo at master · xkcoding/spring-boot-demo(代码基本复制自这里)
超详细,新手都能看懂!使用 SpringBoot+Dubbo 搭建一个简单的分布式服务
黑马程序员 Dubbo 快速入门,Java 分布式框架 dubbo 教程
另外使用了“通义灵码”来获取编写建议。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
· 【译】Visual Studio 中新的强大生产力特性
· 2025年我用 Compose 写了一个 Todo App
2021-12-30 AutoCAD 线型比例莫名改变