24、Spring Boot 4 整合 Dubbo 完整教程

做微服务项目的时候,最烦的就是服务间调用,用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的核心特点包括:

  1. 高性能RPC: 基于Netty的NIO通信框架,性能高、延迟低
  2. 服务治理: 支持服务注册与发现、负载均衡、容错机制、服务降级等
  3. 多协议支持: 支持Dubbo、Triple(gRPC)、REST、HTTP等多种协议
  4. 多注册中心: 支持ZooKeeper、Nacos、Consul、Eureka等多种注册中心
  5. 服务降级: 支持服务降级、熔断、限流等容错机制
  6. 监控管理: 提供Dubbo Admin控制台,可以监控和管理服务

Dubbo的核心概念

  1. 服务提供者(Provider): 暴露服务的服务提供方,启动时向注册中心注册自己提供的服务
  2. 服务消费者(Consumer): 调用远程服务的服务消费方,启动时向注册中心订阅自己所需的服务
  3. 注册中心(Registry): 服务注册与发现的中心,比如ZooKeeper、Nacos等
  4. 监控中心(Monitor): 统计服务的调用次数和调用时间的监控中心
  5. 服务接口(Service Interface): 定义服务的方法签名,供提供者和消费者使用
  6. 服务实现(Service Implementation): 服务接口的具体实现
  7. 负载均衡(Load Balance): 在多个服务提供者之间进行负载均衡
  8. 容错机制(Fault Tolerance): 服务调用失败时的容错策略,比如重试、降级等

Dubbo和Spring Cloud的区别

  1. 通信方式: Dubbo使用RPC调用,性能更高;Spring Cloud使用HTTP调用,更通用
  2. 服务治理: Dubbo内置服务治理功能;Spring Cloud需要集成多个组件
  3. 协议支持: Dubbo支持多种协议;Spring Cloud主要支持HTTP
  4. 性能: Dubbo性能更好,延迟更低;Spring Cloud性能相对较低
  5. 生态: Spring Cloud生态更完善;Dubbo生态相对较小
  6. 适用场景: 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 + ", 用户名=张三, 邮箱=zhangsan@example.com";
    }
    /**
     * 创建用户
     */
    @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("李四", "lisi@example.com");
        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);
    }
}

负载均衡策略说明

  1. random(随机): 随机选择服务提供者,适合服务提供者性能相近的场景
  2. roundrobin(轮询): 按顺序轮流选择服务提供者,适合服务提供者性能相近的场景
  3. leastactive(最少活跃): 选择活跃数最少的服务提供者,适合服务提供者性能差异较大的场景
  4. 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);
    }
}

容错策略说明

  1. failover(失败重试): 调用失败后自动重试其他服务提供者,适合读操作
  2. failfast(快速失败): 调用失败后立即抛出异常,不重试,适合写操作
  3. failsafe(失败安全): 调用失败后返回空结果,不抛出异常,适合日志记录等非关键操作
  4. failback(失败自动恢复): 调用失败后记录失败请求,定时重试,适合消息通知等场景
  5. 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的官方文档,或者给鹏磊留言,咱一起探讨。

本文章最后更新于 2025-12-08