做微服务项目的时候,最烦的就是服务间调用,用HTTP吧,性能差、序列化开销大;用gRPC吧,生态不够完善;后来听说Apache Dubbo这玩意儿不错,高性能RPC框架、服务治理一应俱全,而且还是生产级方案,性能高、功能全;但是直接用Dubbo写,那叫一个复杂,服务注册、服务发现、负载均衡、容错机制、配置管理,一堆配置写得人头疼;后来发现Dubbo Spring Boot Starter直接把这些都封装好了,用起来贼简单;现在Spring Boot 4出来了,整合Dubbo更是方便得不行,自动配置给你整得明明白白,咱今天就聊聊Spring Boot 4咋整合Dubbo的。
其实Dubbo在Spring Boot里早就支持了,你只要加个dubbo-spring-boot-starter依赖,配合注册中心(ZooKeeper、Nacos等),基本上就能用;但是很多兄弟不知道里面的门道,也不知道咋用服务注册、服务发现、负载均衡、容错机制、服务降级、多协议支持这些高级功能,更不知道咋和Spring Cloud、Spring Cloud Alibaba无缝集成,所以鹏磊今天就给兄弟们掰扯掰扯。
Dubbo基础概念
Dubbo是啥玩意儿
Apache Dubbo是一个高性能、轻量级的开源Java RPC框架,致力于提供高性能和透明化的RPC远程服务调用方案,以及SOA服务治理方案;Dubbo的核心特点包括:
- 高性能RPC: 基于Netty的NIO通信框架,性能高、延迟低
- 服务治理: 支持服务注册与发现、负载均衡、容错机制、服务降级等
- 多协议支持: 支持Dubbo、Triple(gRPC)、REST、HTTP等多种协议
- 多注册中心: 支持ZooKeeper、Nacos、Consul、Eureka等多种注册中心
- 服务降级: 支持服务降级、熔断、限流等容错机制
- 监控管理: 提供Dubbo Admin控制台,可以监控和管理服务
Dubbo的核心概念
- 服务提供者(Provider): 暴露服务的服务提供方,启动时向注册中心注册自己提供的服务
- 服务消费者(Consumer): 调用远程服务的服务消费方,启动时向注册中心订阅自己所需的服务
- 注册中心(Registry): 服务注册与发现的中心,比如ZooKeeper、Nacos等
- 监控中心(Monitor): 统计服务的调用次数和调用时间的监控中心
- 服务接口(Service Interface): 定义服务的方法签名,供提供者和消费者使用
- 服务实现(Service Implementation): 服务接口的具体实现
- 负载均衡(Load Balance): 在多个服务提供者之间进行负载均衡
- 容错机制(Fault Tolerance): 服务调用失败时的容错策略,比如重试、降级等
Dubbo和Spring Cloud的区别
- 通信方式: Dubbo使用RPC调用,性能更高;Spring Cloud使用HTTP调用,更通用
- 服务治理: Dubbo内置服务治理功能;Spring Cloud需要集成多个组件
- 协议支持: Dubbo支持多种协议;Spring Cloud主要支持HTTP
- 性能: Dubbo性能更好,延迟更低;Spring Cloud性能相对较低
- 生态: Spring Cloud生态更完善;Dubbo生态相对较小
- 适用场景: Dubbo适合内部服务调用;Spring Cloud适合对外暴露HTTP接口
注册中心安装和启动
使用ZooKeeper作为注册中心
下载ZooKeeper
从ZooKeeper官网下载最新版本: https://zookeeper.apache.org/releases.html
# 下载ZooKeeper
wget https://archive.apache.org/dist/zookeeper/zookeeper-3.9.1/apache-zookeeper-3.9.1-bin.tar.gz
# 解压
tar -xzf apache-zookeeper-3.9.1-bin.tar.gz
cd apache-zookeeper-3.9.1-bin
启动ZooKeeper
# 复制配置文件
cp conf/zoo_sample.cfg conf/zoo.cfg
# 启动ZooKeeper
bin/zkServer.sh start
# 查看状态
bin/zkServer.sh status
使用Nacos作为注册中心
如果使用Nacos作为注册中心,可以参考之前的Nacos教程安装和启动Nacos。
项目搭建和依赖配置
创建Maven项目
首先你得有个Maven项目,用IDEA或者Eclipse都行,或者直接用Spring Initializr生成;项目结构大概是这样:
spring-boot-dubbo-demo/
├── pom.xml # Maven配置文件
├── api/ # API模块(服务接口定义)
│ └── src/
│ └── main/
│ └── java/
│ └── com/
│ └── example/
│ └── api/
│ └── UserService.java # 用户服务接口
├── provider/ # 服务提供者模块
│ └── src/
│ ├── main/
│ │ ├── java/
│ │ │ └── com/
│ │ │ └── example/
│ │ │ └── provider/
│ │ │ ├── Application.java # 启动类
│ │ │ └── service/
│ │ │ └── UserServiceImpl.java # 用户服务实现
│ │ └── resources/
│ │ └── application.yml # 配置文件
│ └── test/
└── consumer/ # 服务消费者模块
└── src/
├── main/
│ ├── java/
│ │ └── com/
│ │ └── example/
│ │ └── consumer/
│ │ ├── Application.java # 启动类
│ │ └── controller/
│ │ └── UserController.java # 用户控制器
│ └── resources/
│ └── application.yml # 配置文件
└── test/
pom.xml完整配置
这是最关键的,依赖配置不对后面全是坑;Spring Boot 4需要Java 17以上,而且Dubbo版本要选对。
父POM配置
<?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>spring-boot-dubbo-demo</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
<name>Spring Boot 4 Dubbo Demo</name>
<description>Spring Boot 4整合Dubbo示例项目</description>
<modules>
<module>api</module>
<module>provider</module>
<module>consumer</module>
</modules>
<properties>
<java.version>17</java.version>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<dubbo.version>3.3.0</dubbo.version> <!-- Dubbo版本 -->
<spring-boot.version>4.0.0</spring-boot.version> <!-- Spring Boot版本 -->
</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>
</dependencies>
</dependencyManagement>
</project>
API模块POM配置
<?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>com.example</groupId>
<artifactId>spring-boot-dubbo-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>api</artifactId>
<packaging>jar</packaging>
<name>API Module</name>
<description>服务接口定义模块</description>
</project>
服务提供者POM配置
<?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>com.example</groupId>
<artifactId>spring-boot-dubbo-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>provider</artifactId>
<packaging>jar</packaging>
<name>Provider Module</name>
<description>服务提供者模块</description>
<dependencies>
<!-- API模块依赖 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo ZooKeeper Starter(如果使用ZooKeeper) -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-zookeeper-spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo Nacos Starter(如果使用Nacos) -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
服务消费者POM配置
<?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>com.example</groupId>
<artifactId>spring-boot-dubbo-demo</artifactId>
<version>1.0.0</version>
</parent>
<artifactId>consumer</artifactId>
<packaging>jar</packaging>
<name>Consumer Module</name>
<description>服务消费者模块</description>
<dependencies>
<!-- API模块依赖 -->
<dependency>
<groupId>com.example</groupId>
<artifactId>api</artifactId>
<version>${project.version}</version>
</dependency>
<!-- Spring Boot Web Starter -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Dubbo Spring Boot Starter -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo ZooKeeper Starter(如果使用ZooKeeper) -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-zookeeper-spring-boot-starter</artifactId>
</dependency>
<!-- Dubbo Nacos Starter(如果使用Nacos) -->
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-nacos-spring-boot-starter</artifactId>
</dependency>
<!-- Lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
application.yml配置
服务提供者配置
spring:
application:
name: dubbo-provider # 应用名称
# Dubbo配置
dubbo:
application:
name: dubbo-provider # 应用名称
logger: slf4j # 日志框架
# 协议配置
protocol:
name: tri # 协议名称: tri(Triple/gRPC)、dubbo、rest、http等
port: -1 # 端口号,-1表示自动分配端口
# 注册中心配置
registry:
address: zookeeper://127.0.0.1:2181 # ZooKeeper地址
# 如果使用Nacos,可以这样配置:
# address: nacos://127.0.0.1:8848
# 服务扫描配置
scan:
base-packages: com.example.provider.service # 扫描服务实现的包路径
服务消费者配置
spring:
application:
name: dubbo-consumer # 应用名称
# Dubbo配置
dubbo:
application:
name: dubbo-consumer # 应用名称
logger: slf4j # 日志框架
# 注册中心配置
registry:
address: zookeeper://127.0.0.1:2181 # ZooKeeper地址
# 如果使用Nacos,可以这样配置:
# address: nacos://127.0.0.1:8848
# 消费者配置
consumer:
timeout: 3000 # 调用超时时间(毫秒)
retries: 2 # 重试次数
loadbalance: roundrobin # 负载均衡策略: random、roundrobin、leastactive、consistenthash
启动类配置
服务提供者启动类
package com.example.provider;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 服务提供者启动类
* @EnableDubbo注解启用Dubbo功能
*/
@SpringBootApplication
@EnableDubbo // 启用Dubbo,会自动扫描@DubboService注解的服务
public class ProviderApplication {
public static void main(String[] args) {
SpringApplication.run(ProviderApplication.class, args);
System.out.println("Dubbo服务提供者启动成功!");
}
}
服务消费者启动类
package com.example.consumer;
import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* 服务消费者启动类
* @EnableDubbo注解启用Dubbo功能
*/
@SpringBootApplication
@EnableDubbo // 启用Dubbo,会自动扫描@DubboReference注解的引用
public class ConsumerApplication {
public static void main(String[] args) {
SpringApplication.run(ConsumerApplication.class, args);
System.out.println("Dubbo服务消费者启动成功!");
}
}
场景一: 基础服务提供和消费
应用场景
你的微服务需要提供RPC服务,其他服务可以调用这个服务,这是最常见的场景。
定义服务接口
在API模块中定义服务接口:
package com.example.api;
/**
* 用户服务接口
* 定义服务的方法签名,供提供者和消费者使用
*/
public interface UserService {
/**
* 根据用户ID查询用户信息
* @param userId 用户ID
* @return 用户信息
*/
String getUserInfo(Long userId);
/**
* 创建用户
* @param username 用户名
* @param email 邮箱
* @return 用户ID
*/
Long createUser(String username, String email);
}
实现服务接口
在服务提供者模块中实现服务接口:
package com.example.provider.service;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
/**
* 用户服务实现
* @DubboService注解将服务暴露为Dubbo服务
*/
@Slf4j
@Service
@DubboService(
version = "1.0.0", // 服务版本
group = "dev", // 服务分组
timeout = 3000, // 超时时间(毫秒)
retries = 2 // 重试次数
)
public class UserServiceImpl implements UserService {
/**
* 根据用户ID查询用户信息
*/
@Override
public String getUserInfo(Long userId) {
log.info("查询用户信息,用户ID: {}", userId);
// 模拟业务逻辑
return "用户信息: 用户ID=" + userId + ", 用户名=张三, 邮箱[email protected]";
}
/**
* 创建用户
*/
@Override
public Long createUser(String username, String email) {
log.info("创建用户,用户名: {}, 邮箱: {}", username, email);
// 模拟业务逻辑
Long userId = System.currentTimeMillis();
log.info("用户创建成功,用户ID: {}", userId);
return userId;
}
}
消费服务
在服务消费者模块中消费服务:
package com.example.consumer.controller;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制器
* 演示如何消费Dubbo服务
*/
@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserController {
/**
* 注入Dubbo服务
* @DubboReference注解注入远程服务代理
*/
@DubboReference(
version = "1.0.0", // 服务版本,必须和提供者一致
group = "dev", // 服务分组,必须和提供者一致
timeout = 3000, // 超时时间(毫秒)
retries = 2 // 重试次数
)
private UserService userService;
/**
* 查询用户信息
*/
@GetMapping("/{userId}")
public String getUserInfo(@PathVariable Long userId) {
log.info("调用用户服务,用户ID: {}", userId);
// 直接调用服务,就像调用本地方法一样
String userInfo = userService.getUserInfo(userId);
log.info("调用结果: {}", userInfo);
return userInfo;
}
/**
* 创建用户
*/
@GetMapping("/create")
public String createUser() {
log.info("创建用户");
// 调用服务创建用户
Long userId = userService.createUser("李四", "[email protected]");
log.info("用户创建成功,用户ID: {}", userId);
return "用户创建成功,用户ID: " + userId;
}
}
场景二: 负载均衡
应用场景
你的服务有多个实例,需要在这些实例之间进行负载均衡,提高系统的可用性和性能。
配置负载均衡策略
在服务消费者中配置负载均衡策略:
package com.example.consumer.controller;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制器
* 演示负载均衡
*/
@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserController {
/**
* 配置负载均衡策略
* loadbalance参数支持: random(随机)、roundrobin(轮询)、leastactive(最少活跃)、consistenthash(一致性哈希)
*/
@DubboReference(
version = "1.0.0",
group = "dev",
loadbalance = "roundrobin" // 轮询负载均衡
)
private UserService userService;
@GetMapping("/{userId}")
public String getUserInfo(@PathVariable Long userId) {
return userService.getUserInfo(userId);
}
}
负载均衡策略说明
- random(随机): 随机选择服务提供者,适合服务提供者性能相近的场景
- roundrobin(轮询): 按顺序轮流选择服务提供者,适合服务提供者性能相近的场景
- leastactive(最少活跃): 选择活跃数最少的服务提供者,适合服务提供者性能差异较大的场景
- consistenthash(一致性哈希): 根据请求参数进行一致性哈希,相同参数的请求会路由到同一个服务提供者
场景三: 容错机制
应用场景
你的服务调用可能失败,需要容错机制,比如重试、降级等,提高系统的可靠性。
配置容错机制
在服务消费者中配置容错机制:
package com.example.consumer.controller;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制器
* 演示容错机制
*/
@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserController {
/**
* 配置容错机制
* cluster参数支持: failover(失败重试)、failfast(快速失败)、failsafe(失败安全)、failback(失败自动恢复)、forking(并行调用)
*/
@DubboReference(
version = "1.0.0",
group = "dev",
cluster = "failover", // 失败重试
retries = 3, // 重试3次
timeout = 3000 // 超时时间3秒
)
private UserService userService;
@GetMapping("/{userId}")
public String getUserInfo(@PathVariable Long userId) {
return userService.getUserInfo(userId);
}
}
容错策略说明
- failover(失败重试): 调用失败后自动重试其他服务提供者,适合读操作
- failfast(快速失败): 调用失败后立即抛出异常,不重试,适合写操作
- failsafe(失败安全): 调用失败后返回空结果,不抛出异常,适合日志记录等非关键操作
- failback(失败自动恢复): 调用失败后记录失败请求,定时重试,适合消息通知等场景
- forking(并行调用): 并行调用多个服务提供者,只要有一个成功就返回结果,适合实时性要求高的场景
场景四: 服务降级
应用场景
你的服务在高负载情况下需要降级,返回默认值或缓存数据,避免系统崩溃。
实现服务降级
在服务消费者中配置服务降级:
package com.example.consumer.controller;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制器
* 演示服务降级
*/
@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserController {
/**
* 配置服务降级
* mock参数指定降级处理类或方法
*/
@DubboReference(
version = "1.0.0",
group = "dev",
mock = "return null", // 降级时返回null
// 或者指定降级处理类:
// mock = "com.example.consumer.service.UserServiceMock"
// 或者指定降级方法:
// mock = "true" // 使用UserServiceMock类
)
private UserService userService;
@GetMapping("/{userId}")
public String getUserInfo(@PathVariable Long userId) {
String result = userService.getUserInfo(userId);
if (result == null) {
return "服务降级,返回默认值";
}
return result;
}
}
实现降级处理类
package com.example.consumer.service;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
/**
* 用户服务降级处理类
* 当服务不可用时,返回降级结果
*/
@Slf4j
@Component
public class UserServiceMock implements UserService {
@Override
public String getUserInfo(Long userId) {
log.warn("用户服务降级,返回默认值,用户ID: {}", userId);
return "用户服务降级,返回默认用户信息";
}
@Override
public Long createUser(String username, String email) {
log.warn("用户服务降级,无法创建用户");
return -1L; // 返回-1表示创建失败
}
}
场景五: 多协议支持
应用场景
你的服务需要支持多种协议,比如同时支持Dubbo协议和HTTP协议,满足不同场景的需求。
配置多协议
在服务提供者中配置多协议:
dubbo:
application:
name: dubbo-provider
# 配置多个协议
protocols:
# Dubbo协议
dubbo:
name: dubbo
port: 20880
# Triple协议(gRPC)
tri:
name: tri
port: 50051
# REST协议
rest:
name: rest
port: 8080
registry:
address: zookeeper://127.0.0.1:2181
在服务中指定协议
package com.example.provider.service;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
/**
* 用户服务实现
* 指定使用Dubbo协议
*/
@Slf4j
@Service
@DubboService(
version = "1.0.0",
group = "dev",
protocol = "dubbo" // 指定使用Dubbo协议
)
public class UserServiceImpl implements UserService {
@Override
public String getUserInfo(Long userId) {
return "用户信息: " + userId;
}
@Override
public Long createUser(String username, String email) {
return System.currentTimeMillis();
}
}
场景六: 多注册中心
应用场景
你的服务需要注册到多个注册中心,提高系统的可用性。
配置多注册中心
在服务提供者中配置多注册中心:
dubbo:
application:
name: dubbo-provider
protocol:
name: tri
port: -1
# 配置多个注册中心
registries:
# ZooKeeper注册中心
zk:
address: zookeeper://127.0.0.1:2181
# Nacos注册中心
nacos:
address: nacos://127.0.0.1:8848
在服务中指定注册中心
package com.example.provider.service;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
/**
* 用户服务实现
* 指定注册到多个注册中心
*/
@Slf4j
@Service
@DubboService(
version = "1.0.0",
group = "dev",
registry = {"zk", "nacos"} // 指定注册到多个注册中心
)
public class UserServiceImpl implements UserService {
@Override
public String getUserInfo(Long userId) {
return "用户信息: " + userId;
}
@Override
public Long createUser(String username, String email) {
return System.currentTimeMillis();
}
}
场景七: 服务分组和版本
应用场景
你的服务需要支持多版本、多分组,比如开发环境、测试环境、生产环境使用不同的版本和分组。
配置服务分组和版本
package com.example.provider.service;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;
/**
* 用户服务实现
* 配置服务分组和版本
*/
@Slf4j
@Service
@DubboService(
version = "1.0.0", // 服务版本
group = "dev" // 服务分组: dev(开发)、test(测试)、prod(生产)
)
public class UserServiceImpl implements UserService {
@Override
public String getUserInfo(Long userId) {
return "用户信息: " + userId;
}
@Override
public Long createUser(String username, String email) {
return System.currentTimeMillis();
}
}
在消费者中指定版本和分组
package com.example.consumer.controller;
import com.example.api.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用户控制器
* 指定服务版本和分组
*/
@Slf4j
@RestController
@RequestMapping("/api/user")
public class UserController {
/**
* 指定服务版本和分组
* 必须和提供者的版本和分组一致
*/
@DubboReference(
version = "1.0.0", // 服务版本
group = "dev" // 服务分组
)
private UserService userService;
@GetMapping("/{userId}")
public String getUserInfo(@PathVariable Long userId) {
return userService.getUserInfo(userId);
}
}
场景八: 参数验证
应用场景
你的服务需要参数验证,确保传入的参数符合要求。
实现参数验证
在服务接口中使用JSR-303验证注解:
package com.example.api;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Positive;
/**
* 用户服务接口
* 使用JSR-303验证注解
*/
public interface UserService {
/**
* 根据用户ID查询用户信息
* @param userId 用户ID,必须大于0
* @return 用户信息
*/
String getUserInfo(@NotNull @Positive Long userId);
/**
* 创建用户
* @param username 用户名,不能为空
* @param email 邮箱,不能为空
* @return 用户ID
*/
Long createUser(@NotNull String username, @NotNull String email);
}
启用参数验证
在服务提供者中启用参数验证:
dubbo:
application:
name: dubbo-provider
protocol:
name: tri
port: -1
registry:
address: zookeeper://127.0.0.1:2181
# 启用参数验证
provider:
validation: true # 启用JSR-303验证
最佳实践
1. 服务接口设计建议
- 服务接口要稳定,避免频繁变更
- 参数和返回值要使用可序列化的类型
- 避免使用大对象作为参数,影响性能
- 合理设计接口粒度,避免接口过于复杂
2. 版本管理建议
- 使用语义化版本号,比如1.0.0、1.1.0、2.0.0
- 大版本升级要谨慎,避免破坏兼容性
- 小版本升级要保持兼容性
- 使用服务分组区分不同环境
3. 性能优化建议
- 合理设置超时时间,避免长时间等待
- 合理设置重试次数,避免过度重试
- 使用连接池,提高连接复用率
- 使用异步调用,提高并发性能
4. 监控和运维建议
- 使用Dubbo Admin监控服务状态
- 配置服务降级,提高系统可用性
- 定期检查服务健康状态
- 记录详细的日志,方便排查问题
5. 安全建议
- 使用服务分组隔离不同环境
- 配置服务访问权限
- 使用TLS加密通信
- 定期更新Dubbo版本
总结
Spring Boot 4整合Dubbo确实方便,高性能RPC、服务治理一应俱全,用起来贼爽;但是要真正用好Dubbo,还得掌握服务注册、服务发现、负载均衡、容错机制、服务降级、多协议支持这些高级功能;鹏磊今天给兄弟们掰扯了Dubbo的基础概念、注册中心安装、项目搭建、各种场景、最佳实践,希望能帮到兄弟们;如果还有啥不明白的,可以看看Dubbo的官方文档,或者给鹏磊留言,咱一起探讨。