dubbo的定义是:
Apache Dubbo 是一款高性能、轻量级的开源RPC框架,用于构建分布式服务系统。
所以我们先来讲一下rpc。
RPC相关知识
什么是 RPC?
定义:
允许程序像调用本地方法一样调用远程服务,隐藏网络细节。
生活类比:
- 🏠 本地调用:直接走到隔壁办公室找同事
 - 🌍 RPC:通过电话呼叫海外同事,但体验如同面对面交谈
 
RPC 核心思想
- 
透明性
- 开发者无需处理网络通信(序列化、传输、错误)
 
 - 
简化分布式系统
- 跨机器调用 → 本地函数调用
 
 
            
            
              arduino
              
              
            
          
          +-------------+      +-------------+
|   Client    |      |   Server    |
| (调用本地方法) | →网络→ | (执行远程方法) |
+-------------+      +-------------+
        RPC 工作原理
四步流程:
- 
客户端代理
- 序列化参数(如 Protobuf/JSON)
 
 - 
网络传输
- 通过 HTTP/TCP 发送请求
 
 - 
服务端处理
- 反序列化 → 执行业务 → 序列化结果
 
 - 
返回响应
- 客户端解析结果
 
 
RPC 核心组件
| 组件 | 作用 | 典型技术 | 
|---|---|---|
| 序列化协议 | 对象 ↔ 字节流 | Protobuf, JSON | 
| 传输协议 | 数据传输通道 | HTTP/2, TCP | 
| 服务发现 | 动态定位服务地址 | ZooKeeper, Consul | 
| 负载均衡 | 请求分发策略 | 轮询, 一致性哈希 | 
RPC 的优缺点
✅ 优点:
- 开发高效(隐藏网络细节)
 - 高性能(二进制协议)
 - 跨语言支持(如 gRPC)
 
❌ 缺点:
- 接口强耦合(需同步升级)
 - 调试复杂(需链路追踪工具)
 
讨论题:
何时应避免使用 RPC? (答案:开放 API 需要高灵活性时)
常见 RPC 框架
| 框架 | 特点 | 适用场景 | 
|---|---|---|
| gRPC | HTTP/2 + Protobuf,高性能 | 内部微服务 | 
| Dubbo | 服务治理(熔断、降级) | 企业级 Java 系统 | 
| Thrift | 多协议支持(TCP/HTTP) | 跨语言系统 | 
RPC vs RESTful API
| 维度 | RPC | RESTful | 
|---|---|---|
| 协议 | 自定义二进制协议(高效) | HTTP + 文本(灵活) | 
| 耦合性 | 高(接口强依赖) | 低(资源导向) | 
| 场景 | 内部服务通信 | 开放 API | 
思考题:
为什么微服务架构常用 RPC?
典型应用场景
- 
微服务通信
- 订单服务 → 支付服务
 
 - 
分布式计算
- Spark 节点任务调度
 
 - 
实时系统
- 游戏服务器状态同步
 
 
什么是Dubbo?
- 定义:Dubbo 是一款高性能、轻量级的开源RPC框架,用于构建分布式服务系统。
 - 核心目标:简化服务间的远程调用,提供服务治理能力(负载均衡、容错、服务发现等)。
 - 适用场景:微服务架构、高并发分布式系统
 
核心特性
- 高性能:基于Netty的NIO通信,支持多种协议(默认Dubbo协议)。
 - 透明化远程调用:像调用本地方法一样调用远程服务。
 - 服务治理:动态配置、流量调度、服务降级、鉴权等。
 
角色说明
- Provider:服务提供者,暴露服务接口。
 - Consumer:服务消费者,调用远程服务。
 - Registry(注册中心):服务注册与发现(推荐使用Zookeeper、Nacos)。
 
环境搭建
创建一个这样的项目,api模块是公共模块
 父项目引入公共依赖jar包
            
            
              xml
              
              
            
          
          <dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <version>1.18.24</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.4.14</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo</artifactId>
    <version>3.3.0</version>
</dependency>
<dependency>
     <groupId>org.springframework</groupId>
     <artifactId>spring-context</artifactId>
     <version>6.1.10</version>
</dependency>
        第一个Dubbo程序开发
这里没有使用 springboot ,用于了解 dubbo 的具体过程,如果学着比较吃力可以跳过,后面我会讲springboot下的使用
api模块开发
定义在api模块中
定义一个业务接口
            
            
              java
              
              
            
          
          public interface UserService {
    boolean login(String name, String password);
}
        Provider开发
引入api模块依赖
记得写成你自己的名字,不要复制粘贴
如果无法引入,先在 api 模块执行 install 命令
            
            
              xml
              
              
            
          
          <dependency>
     <groupId>com.huang.dubbo</groupId>
     <artifactId>dubbo-api</artifactId>
     <version>1.0-SNAPSHOT</version>
</dependency>
        实现具体的业务逻辑
实现我们刚才在api模块中定义的接口,并添加业务逻辑
            
            
              java
              
              
            
          
          @Slf4j
public class UserServiceImpl implements UserService{
    @Override
    public boolean login(String name, String password) {
        log.info("用户登录,姓名:{},密码:{}", name, password);
        return false;
    }
}
        编写spring配置文件
名字随便叫什么都可以
            
            
              xml
              
              
            
          
          <?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans  
                           http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo">
<!--    名称-->
    <dubbo:application name="dubbo-provider"/>
<!--    协议和端口-->
    <dubbo:protocol name="dubbo" port="20880"/>
<!--    创建对象-->
    <bean id="userService" class="com.huang.dubbo.service.UserServiceImpl"/>
<!--    发布一个dubbo的服务,可以被消费者调用-->
    <dubbo:service interface="com.huang.dubbo.service.UserService" ref="userService"/>
</beans>
        编写启动类
            
            
              java
              
              
            
          
          public class ProviderMain {
    public static void main(String[] args) {
        // 创建 spring 工厂加载配置文件,这个文件名字要和你刚才写的文件名一样
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("application.xml");
        
        applicationContext.start();
        // 阻塞主线程
        try {
            new CountDownLatch(1).await();
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
    }
}
        启动之后可以在控制台看到dubbo暴露的服务信息
其中的:dubbo://192.168.1.119:20880/com.huang.dubbo.service.UserService (注意去找你自己控制台的)
在后面会用到
项目结构
Consumer开发
引入api依赖
            
            
              xml
              
              
            
          
          <dependency>
    <groupId>com.huang.dubbo</groupId>
    <artifactId>dubbo-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
        创建配置文件
通过 dubbo 封装的功能获取 provider 提供的 rpc 服务
            
            
              xml
              
              
            
          
          <?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo">
<!--    给服务起一个名字-->
    <dubbo:application name="dubbo-consumer"/>
<!--通过dubbo获取远端的 rpc 服务-->
<!--    参数说明: id:provider 中的服务对象 id ,url:provider 控制台中打印的服务信息-->
    <dubbo:reference interface="com.huang.dubbo.service.UserService" id="userService" url="dubbo://192.168.1.119:20880/com.huang.dubbo.service.UserService"/>
</beans>
        创建启动类
            
            
              java
              
              
            
          
          public class ConsumerApplication {
    public static void main(String[] args) {
        // 创建 spring 工厂加载配置文件
        ClassPathXmlApplicationContext applicationContext =
                new ClassPathXmlApplicationContext("application.xml");
        // 获取 bean
        UserService userService = (UserService) applicationContext.getBean("userService");
        // 获取返回值
        boolean bool = userService.login("huang", "123456");
        System.out.println("ref = " + bool);
        // 阻塞主线程
        try {
            System.in.read();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }
}
        启动程序就可以看到效果了,consumer 调用了 provider 的程序,并获得了返回值。
项目结构
解决报错问题
在 consumer 服务中,你可以找到如下的报错信息
原因:
qos是Dubbo的在线运维命令,可以对服务进行动态的配置、控制及查询,Dubbo2.5.8新版本重构了 telnet (2.0.5开始支持)模块,提供了新的 telnet 命令支持,新版本的 telnet 端口与 dubbo 协议的端口不是同一端口,默认为22222。
在同一台服务器(电脑)里面,启动 provider 时 22222 端口已经被使用,所有 consumer 启动就会报错
解决方案:
在配置文件中进行配置
            
            
              xml
              
              
            
          
          <dubbo:parameter key="qos.enable" value="true"/>   <!-- 是否开启在线运维命令 -->
<dubbo:parameter key="qos.accept.foregin.ip" value="false"/>  <!-- 不允许其他机器的访问 -->
<dubbo:parameter key="qos.port" value="33333"/>   <!-- 修改port -->
        springboot中的配置:
            
            
              properties
              
              
            
          
          dubbo.application.qos.enable=true
dubbo.application.qos.accept.foregin.ip=false
dubbo.application.qos.port=33333
        修改后的 consumer 配置文件:
            
            
              xml
              
              
            
          
          <?xml version="1.0" encoding="UTF-8" ?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
                           http://www.springframework.org/schema/beans/spring-beans.xsd http://dubbo.apache.org/schema/dubbo http://dubbo.apache.org/schema/dubbo/dubbo.xsd"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo">
<!--    给服务起一个名字-->
    <dubbo:application name="dubbo-consumer">
            <dubbo:parameter key="qos.enable" value="false"/>
    </dubbo:application>
<!--通过dubbo获取远端的 rpc 服务-->
<!--    参数说明: id:provider 中的服务对象 id ,url:provider 控制台中打印的服务信息-->
    <dubbo:reference interface="com.huang.dubbo.service.UserService" id="userService" 
                     url="dubbo://192.168.1.119:20880/com.huang.dubbo.service.UserService"/>
</beans>
        把<dubbo:parameter key="qos.enable" value="false"/> 加到 <dubbo:application> 标签里面
可以思考一下,duboo 在这个流程中具体干了什么
基于 SpringBoot 的方式使用Dubbo
自己先创建两个springboot项目(provider和consumer),api模块可以继续使用上面的这个,也可以重新创建一个。
构建provider模块
引入依赖
            
            
              xml
              
              
            
          
          <dependency>
    <groupId>com.huang.dubbo</groupId>
    <artifactId>dubbo-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>
        填写配置文件
            
            
              yaml
              
              
            
          
          spring:
  application:
    name: dubbo-boot-provider #应用名称
dubbo:
  protocol:
    name: dubbo #配置协议
    port: -1 #配置端口,-1 会自动选择
        编写业务逻辑
创建一个类实现我们在 api 模块中定义的接口,并加上@DubboService注解
            
            
              java
              
              
            
          
          @DubboService
public class UserServiceImpl implements UserService{
    @Override
    public boolean login(String name, String password) {
        System.out.println("用户登录,姓名:" + name + ",密码:" + password);
        return false;
    }
}
        编写启动类
在启动类加上@EnableDubbo
            
            
              java
              
              
            
          
          @EnableDubbo  // 开启 Dubbo 功能
@SpringBootApplication
public class ProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(ProviderApplication.class, args);
    }
}
        构建Consumer模块
引入依赖
            
            
              xml
              
              
            
          
          <dependency>
    <groupId>com.huang.dubbo</groupId>
    <artifactId>dubbo-api</artifactId>
    <version>1.0-SNAPSHOT</version>
</dependency>
<dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-spring-boot-starter</artifactId>
    <version>3.3.1</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
</dependency>
        填写配置文件
            
            
              yaml
              
              
            
          
          spring:
  application:
    name: dubbo-boot-consumer #配置应用名
dubbo:
  application:
    qos-enable: false # 关闭qos
        使用 springboot 的测试类进行测试
            
            
              java
              
              
            
          
          @SpringBootTest
public class ConsumerTest {
    // url 还是在控制台找,和上面使用 spring 时是一样的
    @DubboReference(url = "dubbo://192.168.1.119:20880/com.huang.dubbo.service.UserService")
    private UserService userService;
    @Test
    public void test() {
        // 发起远程调用,获得返回值
        boolean ret = userService.login("huang", "123456");
        System.out.println("ret = " + ret);
    }
}
        直接运行单元测试就可以看到效果了
注解解析
简单介绍一下各个注解的功能
@EnableDubbo
作用:
- 
@EnableDubbo注解用于扫描@DubboService并把对应的对象实例化,并发布成 RPC 服务。扫描路径:应用这个注解的类(启动类)所在的包及其子包
 - 
如果
@DubboService注解修饰的类没有放到@EnableDubbo注解修饰的类当前包及其子包,可以使用@DubboComponentScan("basePackages")来指定扫描路径 - 
还可以在配置文件中进行配置
 
            
            
              yaml
              
              
            
          
          dubbo:
  scan:
    base-packages: com.haung.dubbo # 扫描的包
        @DubboService
- 使用了
@DubboService注解修饰的类型, SpringBoot 会创建这个类型的对象,并发布成 Dubbo 服务 @DubboService等同于@Component等注解创建对象的作用
考虑兼容性,建议实现类不仅加上
@DubboService注解,也加上@Service注解
@DubboReference
- 在 Consumer 端,通过
@DubboReference,注入远端服务的代理对象 @DubboReference类似于原始Spring开发中@Autowired注解的作用
等同于dubbo:reference 标签的效果
使用 Nacos 作为注册中心实现自动服务发现
演示 Nacos 作为注册中心实现自动服务发现,示例基于 Spring Boot 应用展开
添加依赖
            
            
              xml
              
              
            
          
          <dependency>
    <groupId>org.apache.dubbo</groupId>
    <artifactId>dubbo-nacos-spring-boot-starter</artifactId>
    <version>3.3.0</version>
</dependency>
        配置并启用 Nacos
            
            
              yaml
              
              
            
          
          dubbo:
 registry:
   address: nacos://localhost:8848
   register-mode: instance # 新用户请设置此值,表示启用应用级服务发现,可选值 interface、instance、all,默认值为 all,未来版本将切换默认值为 instance
        如果需要认证:
            
            
              yaml
              
              
            
          
          dubbo:
 registry:
   address: nacos://localhost:8848?username=nacos&password=nacos
   register-mode: instance
        注册消费者
Dubbo 3.0.0 版本以后,增加了是否注册消费者的参数,如果需要将消费者注册到 nacos 注册中心上,需要将参数(register-consumer-url)设置为true,默认是false。
            
            
              yaml
              
              
            
          
          dubbo:
  registry:
    address: nacos://localhost:8848
    register-mode: instance  # 新用户请设置此值,表示启用应用级服务发现,可选值 interface、instance、all
    parameters.register-consumer-url: true
        其他的基本不变,还有就是@DubboReference直接加在属性上就可以完成注入,不需要url