Bootstrap

《孙哥说》Dubbo3 第一章

  • 💌 所属专栏:【Dubbo3】
  • 😀 作 者:长安不及十里
  • 💻 工作:目前从事电力行业开发
  • 🌈 目标:全栈开发
  • 🚀 个人简介:一个正在努力学技术的Java工程师,专注基础和实战分享 ,欢迎咨询!
  • 💖 欢迎大家:这里是CSDN,我总结知识的地方,喜欢的话请三连,有问题请私信 😘 😘 😘

  • 参考资料:

Apache Dubbo 中文

  • 参考课程

Dubbo3实战开发一套通:分布式微服务解决方案、全方位一网打尽|Nacos、gRPC、Triple、Consul、Zookeeper、SpringCloud_哔哩哔哩_bilibili

一 认识Dubbo

1.1 认识Dubbo

  1. 早期Dubbo的定位,基于JAVA的⾼性能,轻量级RPC框架 【high-performance, lightweight,Java-based RPC framework】,SOA【Service-Oriented Architecture ⾯向服务的架构】 = RPC+服务治理。
  2. 2018年阿⾥巴巴把这个框架捐献给了 Apache 基⾦会,正式更名为Apache Dubbo。
  3. 最新版本为Dubbo3.x,Apache Dubbo 是⼀款易⽤、⾼性能的 WEB 和 RPC 框架,同时为构建企业级微服务提供服务发现、流量治理、可观测、认证鉴权等能⼒、⼯具与最佳实践。
  4. Dubbo3 已在阿⾥巴巴内部微服务集群全⾯落地,成功取代运⾏多年的HSF 框架。依托于Dubbo3,阿⾥提出了⾃⼰的微服务解决⽅案DNS。
  5. 经过孵化,Dubbo⽬前成为Apache的顶级项⽬。

官⽅⽹站:
Apache Dubbo 中文
GitHub :
GitHub - apache/dubbo: The java implementation of Apache Dubbo. An RPC and microservice framework.

1.2 SOA与微服务

时⾄今⽇,SOA与微服务架构基本可以统⼀成⼀个概念了。

1.2.1 单体架构

image.png
特点:

  1. 单一部署单元: 整个应用作为一个单一的单元进行部署。
  2. 紧密耦合: 所有组件和模块紧密结合在一起,共享同一个代码库和数据存储。
  3. 开发简单: 初期开发相对简单,因为所有功能都在一个应用中。
  4. 易于理解和维护: 由于应用结构相对简单,因此更容易理解和维护。

优点:

  1. 开发简单快速: 初始阶段开发速度快,因为所有组件都在一个代码库中。
  2. 部署容易: 部署简单,只需将整个应用程序部署到服务器即可。
  3. 易于调试: 整体代码在一处,调试相对容易。

缺点:

  1. 扩展困难: 随着应用规模增长,单体架构难以扩展,可能导致性能问题。
  2. 复杂性增加: 随着时间推移,单体应用的代码库会变得庞大复杂,难以维护和理解。
  3. 技术选型受限: 难以采用新技术,因为整个应用程序需要统一的技术栈。
  4. 团队协作挑战: 大团队协作时,多人修改同一个代码库可能导致冲突。

1.2.2 水平扩展

image.png
特点:

  1. 增加实例数量: 水平扩展通过增加相同资源实例的数量来处理更多的负载。
  2. 分布式架构: 资源实例分布在多个节点或服务器上,共同处理请求。
  3. 弹性和伸缩性: 可根据需求动态地增加或减少实例数量,以应对流量波动。
  4. 平行处理能力: 实例并行处理请求,提高系统整体的吞吐量和性能。

优点:

  1. 高可用性: 分布在多个实例上,当一个实例出现故障时,其他实例可以继续提供服务,提高系统的可用性。
  2. 扩展性: 可根据需求快速地扩展系统能力,应对增加的负载。
  3. 性能提升: 增加实例可以提高系统整体的并发处理能力,提升性能表现。

缺点:

  1. 数据一致性: 在分布式环境下,确保数据一致性可能变得更加复杂。
  2. 部署和管理复杂性: 管理大量的实例可能会增加部署和监控的复杂性。
  3. 成本增加: 增加实例数量可能会导致资源成本的增加,特别是在负载低时,维护多个实例可能造成资源浪费。

1.2.3 垂直扩展

image.png
特点:

  1. 单一节点增强: 垂直扩展是在单个节点上增加资源,而不是增加多个节点。
  2. 相对简单: 相对于水平扩展(添加更多的节点),垂直扩展通常更为直接和简单。

优点:

  1. 易于管理: 管理一个大节点比管理多个节点更简单。
  2. 适用性广泛: 对于一些应用来说,垂直扩展是更经济的解决方案,尤其是在资源需求不是线性增长的情况下。
  3. 性能提升明显: 增加单个节点的资源可以显著提高性能,尤其是对于需要大量内存或处理能力的应用。

缺点:

  1. 硬件限制: 有物理限制,不能无限制地增加资源,达到某个点后无法再进行扩展。
  2. 单点故障: 如果垂直扩展后的节点发生故障,系统可能会完全失效,而水平扩展可以通过其他节点来保持系统的可用性。
  3. 成本高昂: 在某些情况下,购买更高规格的硬件可能比增加多个普通规格的硬件更昂贵。

1.2.4 RPC架构[Remote Procedure CaLL]

image.png
特点:

  1. 封装远程调用: 允许程序像调用本地函数一样调用远程服务,隐藏了底层的网络通信细节。
  2. 跨语言支持: 可以支持不同编程语言之间的通信,使得异构系统能够相互调用。
  3. 支持不同协议: 可以使用多种协议,如HTTP、TCP等,来进行远程调用。
  4. 提供接口定义: 常常会使用IDL(接口定义语言)来定义服务接口,使得不同系统可以基于相同的接口进行交互。

优点:

  1. 抽象复杂性: 隐藏了网络通信的细节,使得远程调用看起来像本地调用,降低了开发者的复杂性。
  2. 模块化和分布式: 允许系统模块化部署,让不同模块能够分布在不同的服务器上,提高系统的灵活性和可伸缩性。
  3. 易于扩展: 可以方便地添加新的远程服务,而不需要修改现有系统的架构。

缺点:

  1. 性能开销: 额外的序列化、网络传输和反序列化会增加一定的性能开销。
  2. 网络故障: 如果网络出现故障,会导致远程调用失败,需要实施容错机制以应对这种情况。
  3. 调试困难: 由于远程调用隐藏了底层细节,调试时可能难以追踪问题。

1.2.5 SOA架构[Service-Oriented Architecture]

SOA架构是RPC架构的演化。代表框架Dubbo

  • RPC 架构的问题

image.png

  • SOA 架构

image.png

  • 服务总线

image.png
SOA(面向服务的架构)是一种设计方法,将软件系统划分为多个独立的、可重用的服务,这些服务通过标准化的接口进行通信和交互。
特点:

  1. 服务独立性: 服务是独立的功能单元,可以被独立开发、部署和升级。
  2. 松耦合: 服务之间通过定义良好的接口进行通信,使得系统模块之间的耦合度降低。
  3. 服务重用: 可以在不同的应用程序中重用服务,提高了开发效率和系统的灵活性。
  4. 标准化接口: 服务之间通常使用标准化的接口进行通信,如SOAP、REST等。

优点:

  1. 灵活性和可扩展性: SOA允许系统灵活地添加、移除或更改服务,以适应业务需求的变化。
  2. 跨平台和跨语言: 可以实现不同平台和不同语言之间的互操作性,增强了系统的整合性。
  3. 提高组织效率: 可以提高开发团队的效率,因为可以复用现有的服务,而不必重复开发相同的功能。

缺点:

  1. 复杂性: 将系统拆分为多个服务,需要良好的设计和管理,增加了系统的复杂性。
  2. 性能问题: 服务间通信可能引入额外的网络开销和延迟,需要考虑性能问题。
  3. 安全性隐患: 分布式的特性可能会增加安全风险,需要考虑对服务的安全性进行有效管理。

1.2.6 微服务架构

微服务是SOA架构的升级,在微服务体系统中,没有⼦系统了,全部都是服务化功能。微服务架构代表框架,SpringCloud, DNS(Dubbo+Nacos+Sentinel)

image.png
微服务架构是一种软件架构模式,将应用程序设计为一组小型、自治的服务单元,每个服务专注于完成特定的业务功能。这些服务可以独立开发、部署、扩展和管理,通过轻量级通信机制(如HTTP或消息队列)相互协作,共同构建一个大型复杂的应用系统。
特点:

  1. 服务拆分: 将应用程序拆分成多个小型服务,每个服务都有自己的数据存储、业务逻辑和用户界面。
  2. 自治性: 每个服务都是自治的,可以独立部署和扩展,服务之间通过明确定义的接口进行通信。
  3. 分布式和去中心化: 微服务架构支持分布式部署,没有单点故障,并且可以根据需求选择不同的技术栈。
  4. 弹性和可伸缩性: 可以根据需求对单个服务进行水平或垂直扩展,以应对负载变化。
  5. 技术多样性: 不同服务可以使用不同的编程语言、框架和技术栈,使得团队可以选择最适合其需求的工具。

优点:

  1. 灵活性和可维护性: 小型服务更易于理解、开发和维护,有利于团队协作和快速迭代。
  2. 高可用性和容错性: 分布式架构使系统更加鲁棒,单个服务故障不会影响整个系统。
  3. 扩展性: 可以根据需求对单个服务进行独立扩展,而无需整体扩展整个应用。
  4. 技术栈灵活性: 不同服务可以使用最适合其需求的技术,提高了开发效率和系统灵活性。

挑战:

  1. 复杂性: 微服务架构引入了分布式系统的复杂性,包括服务间通信、一致性、监控和部署等方面的挑战。
  2. 分布式事务: 多个服务之间的事务管理可能更为复杂,需要仔细设计和实施。
  3. 部署和监控: 需要有效的部署管道和监控系统来确保服务的可靠性和稳定性。
  4. 团队组织: 需要良好的团队组织和沟通机制,以便不同团队协作开发和维护各自的服务。

1.3 Dubbo3 升级点

● **易⽤性 **
开箱即⽤易⽤性⾼,如 Java 版本的⾯向接⼝代理特性能实现本地透明调⽤功能丰富,基于原⽣库或轻量扩展即可实现绝⼤多数的微服务治理能⼒。更加完善了多语⾔⽀持(GO PYTHON RUST)
超⼤规模微服务实践 **
○ ⾼性能通信(Triple GRPC)
○ ⾼可扩展性 (SPI 多种序列化⽅式 多种协议)
○ 丰富的服务治理能⼒
○ 超⼤规模集群实例⽔平扩展
云原⽣ **
○ 容器调度平台(Kubernetes)
将服务的组织与注册交给底层容器平台,如 Kubernetes,这是更云原⽣的⽅式。
○ Service Mesh
原有Mesh结构中通过Sidecar完成负载均衡、路由等操作,但是存在链路的性能损耗⼤,现有系统迁移繁琐等问题。 Dubbo3 引⼊Proxyless Mesh,直接和I控制⾯交互[istio]通信。集成ServiceMesh更为⽅便,效率更⾼。

1.4 谁在参与建设、使⽤Dubbo3

阿⾥巴巴【电商系统的考拉、交易平台,饿了么、钉钉】、携程、⼯商银⾏、中 国⼈寿、海尔、⾦蝶、⽃⻥、⼩⽶、京东…

二 第⼀个Dubbo程序开发

2.1 专业术语

image.png

  1. provider 功能提供者
  2. consumer 功能调⽤者【功能消费者】
  3. commons-api 通⽤内容 entity service接⼝
  4. registry 注册中⼼ 1. 可选 2. ⽤于管理provider集群

2.2 JDK 与 Dubbo版本对应问题说明

  1. JDK8 与 Dubbo3.1.x以前的版本匹配,在使⽤Zookeeper注册作为注册中
    ⼼时,消费者会出现节点已经存在的异常https://github.com/apache/dubbo/issues/11077
  2. JDK17 与 Dubbo3.1.x之前的版本搭配使⽤会出现如下问题
    a. JDK9之后的深反射问题,需要通过JVM参数配置解决
-Dio.netty.tryReflectionSetAccessible=true
--add-opens
java.base/jdk.internal.misc=ALL-UNNAMED
--add-opens
java.base/java.nio=ALL-UNNAMED
--add-opens
java.base/java.lang=ALL-UNNAMED
b. Dubbo3.2.0.beat4以前的版本使⽤的是Spring5.2.x 不能⽀持 JDK17

会产⽣如下异常,Unsupported class file major version 61 【major 61 对应 17 】
版本需要升级到Dubbo3.2.0.beat5以上版本

2.3 SpringMvc整合Dubbo3

  • 结构

image.png

  • 父依赖
<?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.shu</groupId>
    <artifactId>SpringMvc-Dubbo</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>pom</packaging>

    <modules>
        <module>Dubbo-Provider</module>
        <module>Dubbo-Consumer</module>
        <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>
    </properties>

    <dependencies>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <version>1.18.22</version>
    </dependency>

    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.32</version>
    </dependency>

    <dependency>
        <groupId>ch.qos.logback</groupId>
        <artifactId>logback-classic</artifactId>
        <version>1.2.9</version>
    </dependency>

    <dependency>
        <groupId>org.apache.dubbo</groupId>
        <artifactId>dubbo</artifactId>
        <version>3.2.0</version>
    </dependency>

    </dependencies>

</project>
  • 先建公共Api

image.png
image.png

  • 先建接口
package com.shu.model;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.ToString;

import java.io.Serializable;

/**
 * @author : EasonShu
 * @date : 2023/11/19 12:34
 * @Version: 1.0
 * @Desc : 用户实体类
 */
@Data
@AllArgsConstructor
@NoArgsConstructor
@ToString
public class User implements Serializable {
    private String name;
    private String password;
    private String email;
    private String phone;
}
package com.shu.service;
import com.shu.model.User;

/**
 * @author : EasonShu
 * @date : 2023/11/19 12:35
 * @Version: 1.0
 * @Desc : 用户服务接口
 */
public interface UserService {

    // 通过用户名查询用户信息
    User queryUserByName(String name);

    // 保存用户信息
    void saveUser(User user);
}

  • 新建服务提供者

引入公共依赖

    <dependency>
            <groupId>com.shu</groupId>
            <artifactId>Dubbo-Api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

编写服务接口实现类

package com.shu.service;

import com.shu.model.User;
import com.sun.istack.internal.NotNull;
import lombok.extern.slf4j.Slf4j;


/**
 * @author : EasonShu
 * @date : 2023/11/19 12:37
 * @Version: 1.0
 * @Desc :
 */
@Slf4j
public class UserServiceProvider implements UserService{
    @Override
    public User queryUserByName(String name) {
        log.info("查询用户信息成功");
        return new User("EasonShu", "123456", "[email protected]", "177134e59165");
    }

    @Override
    public void saveUser(@NotNull User user) {
      log.info("保存用户信息成功");
      log.info("用户信息为:{}", user.toString());
    }
}

编写SpringMvc配置文件:applicationContext-provider.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" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       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">
    <dubbo:application name="DubbuoProvider"/>
    <dubbo:protocol name="dubbo" port="-1" />
    <bean id="UserService" class="com.shu.service.UserServiceProvider"/>
    <dubbo:service interface="com.shu.service.UserService" ref="UserService"/>
</beans>

编写启动类

package com.shu;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.concurrent.CountDownLatch;


/**
 * @author : EasonShu
 * @date : 2023/11/19 12:40
 * @Version: 1.0
 * @Desc : Dubbo服务提供者启动类
 */

@EnableDubbo
public class DubboProviderApplication {
    public static void main(String[] args) throws InterruptedException {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-provider.xml");
        applicationContext.start();
        new CountDownLatch(1).await();
    }
}

观察启动日志:ip信息 Dubbo Application1.1 is ready., dubbo version: 3.2.0, current host: 192.168.2.35
image.png

  • 编写消费者

编写配置文件:applicationContext-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" xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       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">
    <dubbo:application name="Dubbo-consuemer">
        <dubbo:parameter key="qos.enable" value="false"/>
    </dubbo:application>
    <dubbo:reference interface="com.shu.service.UserService" id="UserService"
                     url="dubbo://192.168.2.35:20880/com.shu.service.UserService"/>
</beans>

注意qos:
ERROR org.apache.dubbo.qos.server.Server
Address already in use
**问题产⽣的原因: **
Qos=Quality of Service,qos是Dubbo的在线运维命令,可以对服务进⾏动态的配置、控制及查询, Dubboo2.5.8新版本重构了telnet(telnet是从 Dubbo2.0.5开始⽀持的)模块,提供了新的telnet命令⽀ 持,新 版本的telnet端⼝与dubbo协议的端⼝是不同的端⼝, 默认为22222。正是因为这个问题:如果在⼀台服务器 ⾥⾯,启动provider时22222端⼝,⽽consumer启动
时就会报错了。
解决方案
xml

<dubbo:parameter key="qos.enable" value="true"/> <!--
是否开启在线运维命令 -->
<dubbo:parameter key="qos.accept.foreign.ip" value="false"/> <!--
不允许其他机器的访问 -->
<dubbo:parameter key="qos.port" value="33333"/> <!--
修改port-->

yaml

dubbo.application.qos.enable=true
dubbo.application.qos.port=33333
dubbo.application.qos.accept.foreign.ip=false
  • 编写启动类
package com.shu.service;

import com.shu.model.User;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.io.IOException;

/**
 * @author : EasonShu
 * @date : 2023/11/19 12:52
 * @Version: 1.0
 * @Desc :
 */
public class DubboConsumerApplication {
    public static void main(String[] args) throws IOException {
        ClassPathXmlApplicationContext applicationContext = new ClassPathXmlApplicationContext("applicationContext-consumer.xml");
        UserService userService = applicationContext.getBean(UserService.class);
        System.out.println(userService.queryUserByName("EasonShu"));
        userService.saveUser(new User("小米","123456", "", ""));
        System.in.read();
    }
}

  • 启动测试

image.png
image.png

  • 补充
provider基于dubbo协议 默认的端⼝是20880
<dubbo:protocol name="dubbo" port="20880"/>
但是随着应⽤数量过⼤如果显示指定协议端⼝,会容易造成端⼝冲突所以建议按照如下写法设置
端⼝
<dubbo:protocol name="dubbo" port="-1"/>
  • 过程解析:(通信方式,协议,序列化)

image.png

2.4 SpringBoot 与Dubbo3整

深度封装,把公⽤的配置放置到application.yml中,把个性的配置应⽤注解进⾏设置
image.png
image.png

  • 结构

image.png

  • 服务者依赖
<?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.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.shu</groupId>
    <artifactId>Dubbo-Provider-Boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>Dubbo-Provider-Boot</name>

    <properties>
        <maven.compiler.source>8</maven.compiler.source>
        <maven.compiler.target>8</maven.compiler.target>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.shu</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.2.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>
  • 配置文件
spring:
  application:
    name: DUBBO-PROVIDER-BOOT
dubbo:
  protocol:
    name: dubbo
    port: -1
  • 编写代码
package com.shu.service;

import com.shu.model.User;
import com.sun.istack.internal.NotNull;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.stereotype.Service;


/**
 * @author : EasonShu
 * @date : 2023/11/19 12:37
 * @Version: 1.0
 * @Desc : Dubbo服务提供者
 */
@Slf4j
@Service
@DubboService
public class UserServiceProvider implements UserService{
    @Override
    public User queryUserByName(String name) {
        log.info("查询用户信息成功");
        return new User("EasonShu", "123456", "[email protected]", "177134e59165");
    }

    @Override
    public void saveUser(@NotNull User user) {
      log.info("保存用户信息成功");
      log.info("用户信息为:{}", user.toString());
    }
}

  • 启动类
package com.shu;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.concurrent.CountDownLatch;


/**
 * @author : EasonShu
 * @date : 2023/11/19 12:40
 * @Version: 1.0
 * @Desc : Dubbo服务提供者启动类
 */

@EnableDubbo
@SpringBootApplication
public class DubboProviderApplication {
    public static void main(String[] args) throws InterruptedException {
        SpringApplication.run(DubboProviderApplication.class, args);
    }
}

  • 观察启动结果

image.png

  • 编写消费者依赖
<?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.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.7.12</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <groupId>com.shu</groupId>
    <artifactId>Dubbo-Consumer-Boot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>>Dubbo-Consumer-Boot</name>

    <properties>
        <java.version>1.8</java.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-test</artifactId>
            <scope>test</scope>
        </dependency>

        <dependency>
            <groupId>com.shu</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.2.0</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>
  • 配置文件
spring:
  application:
    name: DUBBO-CONSUMER-BOOT

dubbo:
  application:
    qos-enable: false
  • 启动类
package com.shu;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

/**
 * @author : EasonShu
 * @date : 2023/11/19 14:28
 * @Version: 1.0
 * @Desc :
 */
@SpringBootApplication
@EnableDubbo
public class DubboConsumerApplication {
    public static void main(String[] args) {
        SpringApplication.run(DubboConsumerApplication.class, args);
    }
}
  • 测试类
package com.shu;

import com.shu.service.UserService;
import org.apache.dubbo.config.annotation.DubboReference;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;

/**
 * @author : EasonShu
 * @date : 2023/11/19 14:29
 * @Version: 1.0
 * @Desc :
 */
@SpringBootTest
public class DubboConsumerApplicationTest {

    @DubboReference(url = "dubbo://192.168.2.35:20880/com.shu.service.UserService")
    private UserService userService;


    @Test
    public void test() {
        System.out.println(userService.queryUserByName("EasonShu"));
    }


    @Test
    public void test1() {
        userService.saveUser(null);
    }

}
  • 结果

image.png
image.png

2.5 细节分析

@EnableDubbo注解的作⽤

  1. @EnableDubbo ⽤于扫描@DubboService 并把对应的对象实例
    化,发布成RPC服务。
    扫描的路径:应⽤这个注解的类(启动类)所在的包及其⼦包。
  2. 如果@DubboService注解修饰的类没有放到@EnableDubbo注解
    修饰类当前包及其⼦包,还希望能够扫描到它该如何处理?
    可以通过[@DubboComponentScan(basePackages ](/DubboComponentScan(basePackages ) =
    {“org.suns.service”}),显示的指定扫描的路径
  3. yml进⾏配置扫描@DubboService 并把对应的对象实例化,发布
    成RPC服务。
    dubbo.scan.base-packages 等同于 @EnableDubbo

@DubboService注解的作⽤

  1. 应⽤@DubboService注解修饰类型,SpringBoot会创建这个类型
    的对象,并发布成Dubbo服务。
  2. @DubboService 等同于 @Component(@Service) ) @Bean注解的
    创建对象的作⽤。
    通过源码SingletonObjects可以验证
  3. @DubboService
    a. 创建对象 等同于 @Component(@Service) ) @Bean
    b. 发布成RPC服务
  4. 后续开发过程中如果考虑兼容性,建议实现类不仅仅要加⼊
    @DubboService注解,同时也要加⼊@Service注解

@DubboReference注解的作⽤

  1. 在Consumer端,通过@DubboReference,注⼊远端服务的代理
    对象。
  2. @DubboReference类似于原始Spring开发中@Autowired注解的
    作⽤。
;