艿艿周末又肝了一篇万字 Dubbo 文章,Spring Boot + Nacos + Sentinel + 参数校验,美滋滋~...

这篇文章详细介绍了如何在Spring Boot环境中集成Dubbo、Nacos和Sentinel,从XML配置到注解配置,包括服务的提供者和消费者实现,参数验证,自定义异常处理,以及如何使用Nacos作为注册中心和Sentinel进行流量控制。通过实例代码展示了Dubbo服务的完整生命周期,帮助读者深入理解Dubbo的使用和扩展机制。
摘要由CSDN通过智能技术生成

点击上方“芋道源码”,选择“设为星标

管她前浪,还是后浪?

能浪的浪,才是好浪!

每天 8:55 更新文章,每天掉亿点点头发...

源码精品专栏

 
  • 1. 概述

  • 2. XML 配置

  • 3. 注解配置

  • 4. 参数验证

  • 5. 自定义实现拓展点

  • 6. 整合 Nacos

  • 6. 整合 Sentinel

  • 666. 彩蛋


本文在提供完整代码示例,可见 https://github.com/YunaiV/SpringBoot-Labs 的 lab-30 目录。

原创不易,给点个 Star 嘿,一起冲鸭!

1. 概述

在 2019.05.21 号,在经历了 1 年多的孵化,Dubbo 终于迎来了 Apache 毕业。在这期间,Dubbo 做了比较多的功能迭代,提供了 NodeJS、Python、Go 等语言的支持,也举办了多次社区活动,在网上的“骂声”也少了。

艿艿:事实上,大多数成熟的开源项目,都是 KPI 驱动,又或者背后有商业化支撑。

作为一个长期使用,并且坚持使用 Dubbo 的开发者,还是比较愉快的。可能,又经历了一次技术正确的选择。当然,更愉快的是,Spring Cloud Alibaba 貌似,也已经完成孵化,双剑合并,biubiubiu 。

可能胖友有些胖友对 Dubbo 不是很了解,这里艿艿先简单介绍下:

FROM Dubbo 官网

Apache Dubbo |ˈdʌbəʊ| 是一款高性能、轻量级的开源 Java RPC 框架,它提供了三大核心能力:面向接口的远程方法调用,智能容错和负载均衡,以及服务自动注册和发现。

Dubbo 整体架构

图中,一共涉及到 5 个角色:

  • Registry 注册中心,用于服务的注册与发现。

  • Provider 服务提供者,通过向 Registry 注册服务。

  • Consumer 服务消费者,通过从 Registry 发现服务。后续直接调用 Provider ,无需经过 Registry 。

  • Monitor 监控中心,统计服务的调用次数和调用时间。

  • Container 服务运行容器。

FROM 《Dubbo 文档 —— 架构》

调用关系说明(注意,和上图的数字,和下面的步骤是一一对应的):

  1. 服务容器负责启动,加载,运行服务提供者。

    1. 服务提供者在启动时,向注册中心注册自己提供的服务。

    1. 服务消费者在启动时,向注册中心订阅自己所需的服务。

    1. 注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。

    1. 服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。

    1. 服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

本文的重心,在于一起入门 Provider 和 Consumer 的代码编写,这也是实际项目开发中,我们涉及到的角色。

Dubbo 提供了比较多的配置方式,日常开发中主要使用的是 XML 配置 和 注解配置 。我们分别会在 「2. XML 配合」 和 「3. 注解配置」 小节来入门。

考虑到现在 Dubbo 已经提供了 dubbo-spring-boot-project 项目,集成到 Spring Boot 体系中,而大家都基本采用 Spring Boot 框架,所以我们就不像 Dubbo 官方文档 一样,提供的是 Spring 环境下的示例,而是 Spring Boot 环境下

2. XML 配置

示例代码对应仓库:lab-30-dubbo-xml-demo 。

本小节的示例,需要创建三个 Maven 项目,如下图所示:

  • user-rpc-service-api 项目:服务接口,定义 Dubbo Service API 接口,提供给消费者使用。详细代码,我们在 「2.1 API」 讲解。

  • user-rpc-service-provider 项目:服务提供者,实现 user-rpc-service-api 项目定义的 Dubbo Service API 接口,提供相应的服务。详细代码,我们在 「2.2 Provider」 中讲解。

  • user-rpc-service-consumer 项目:服务消费者,会调用 user-rpc-service-provider 项目提供的 Dubbo Service 服务。详细代码,我们在 「2.3 Consumer」 中讲解。

2.1 API

对应 user-rpc-service-api 项目,服务接口,定义 Dubbo Service API 接口,提供给消费者使用。

2.1.1 UserDTO

cn.iocoder.springboot.lab30.rpc.dto 包下,创建用于 Dubbo Service 传输类。这里,我们创建 UserDTO 类,用户信息 DTO 。代码如下:

// UserDTO.java

public class UserDTO implements Serializable {

    /**
     * 用户编号
     */
    private Integer id;
    /**
     * 昵称
     */
    private String name;
    /**
     * 性别
     */
    private Integer gender;
    
    // ... 省略 set/get 方法
}

注意,要实现 java.io.Serializable 接口。因为,Dubbo RPC 会涉及远程通信,需要序列化和反序列化。

2.1.2 UserRpcService

cn.iocoder.springboot.lab30.rpc.api 包下,创建 Dubbo Service API 接口。这里,我们创建 UserRpcService 接口,用户服务 RPC Service 接口。代码如下:

// UserRpcService.java

public interface UserRpcService {

    /**
     * 根据指定用户编号,获得用户信息
     *
     * @param id 用户编号
     * @return 用户信息
     */
    UserDTO get(Integer id);

}

2.2 Provider

对应 user-rpc-service-provider 项目,服务提供者,实现 user-rpc-service-api 项目定义的 Dubbo Service API 接口,提供相应的服务。

2.2.1 引入依赖

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">
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.1.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>user-rpc-service</artifactId>

    <dependencies>
        <!-- 引入定义的 Dubbo API 接口 -->
        <dependency>
            <groupId>cn.iocoder.springboot.labs</groupId>
            <artifactId>user-rpc-service-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>

        <!-- 引入 Spring Boot 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter</artifactId>
        </dependency>

        <!-- 实现对 Dubbo 的自动化配置 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
            <version>2.7.4.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>2.7.4.1</version>
        </dependency>

        <!-- 使用 Zookeeper 作为注册中心 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>2.13.0</version>
        </dependency>
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-recipes</artifactId>
            <version>2.13.0</version>
        </dependency>

    </dependencies>

</project>
  • 因为我们希望实现对 Dubbo 的自动化配置,所以引入 dubbo-spring-boot-starter 依赖。

  • 因为我们希望使用 Zookeeper 作为注册中心,所以引入 curator-frameworkcurator-recipes 依赖。可能胖友不太了解 Apache Curator 框架,这里我们看一段简介:

    FROM https://www.oschina.net/p/curator

    Zookeeper 的客户端调用过于复杂,Apache Curator 就是为了简化Zookeeper 客户端调用而生,利用它,可以更好的使用 Zookeeper。

    • 虽然说,目前阿里正在大力推广 Nacos 作为 Dubbo 的注册中心,但是大多数团队,采用的还是 Zookeeper 为主。

    • 对了,如果胖友不知道怎么安装 Zookeeper ,可以看看 《芋道 Zookeeper 极简入门》 文章。

2.2.2 应用配置文件

resources 目录下, 创建 application.yml 配置文件,添加 Dubbo 相关的配置,如下:

# dubbo 配置项,对应 DubboConfigurationProperties 配置类
dubbo:
  # Dubbo 应用配置
  application:
    name: user-service-provider # 应用名
  # Dubbo 注册中心配
  registry:
    address: zookeeper://127.0.0.1:2181 # 注册中心地址。个鞥多注册中心,可见 http://dubbo.apache.org/zh-cn/docs/user/references/registry/introduction.html 文档。
  # Dubbo 服务提供者协议配置
  protocol:
    port: -1 # 协议端口。使用 -1 表示随机端口。
    name: dubbo # 使用 `dubbo://` 协议。更多协议,可见 http://dubbo.apache.org/zh-cn/docs/user/references/protocol/introduction.html 文档
  # Dubbo 服务提供者配置
  provider:
    timeout: 1000 # 【重要】远程服务调用超时时间,单位:毫秒。默认为 1000 毫秒,胖友可以根据自己业务修改
    UserRpcService:
      version: 1.0.0
  • dubbo-spring-boot-starter 依赖,会根据 dubbo 配置项,实现对 Dubbo 的自动化配置。下面呢,我们来逐个配置项看看。

    艿艿:本小节,我们的 「XML 配置」 ,指的是使用 XML 来配置 Dubbo Service 服务。如果胖友想看纯粹的全量 XML 配置,可以看看 《Dubbo 官方文档 —— XML 配置》 。

  • dubbo.application 配置项,Dubbo 应用信息配置。更多属性,可见 ApplicationConfig 类。每个属性的说明,可见 《Dubbo 文档 —— dubbo:application》 。

  • dubbo.registry 配置项,Dubbo 注册中心配置。更多属性,可见 RegistryConfig 类。每个属性的说明,可见 《Dubbo 文档 —— dubbo:registry》 。

  • dubbo.protocol 配置项,Dubbo 服务提供者协议配置。更多属性,可见 ProtocolConfig 类。每个属性的说明,可见 《Dubbo 文档 —— dubbo:protocol》 。

  • dubbo.provider 配置项,Dubbo 服务提供者配置。更多属性,可见 ProviderConfig 类。每个属性的说明,可见 《Dubbo 文档 —— dubbo:provider》 。

  • dubbo.provider.UserRpcService 配置项,是我们自定义的,设置每个 Service 服务的配置。更多属性,可见 ServiceConfig 类。每个属性的说明,可见 《Dubbo 文档 —— dubbo:service》 。

2.2.3 UserRpcServiceImpl

cn.iocoder.springboot.lab30.rpc.service 包下,创建 Dubbo Service 实现类。这里,我们创建 UserRpcServiceImpl 类,用户服务 RPC Service 实现类。代码如下:

// UserRpcServiceImpl.java

@Service
public class UserRpcServiceImpl implements UserRpcService {

    @Override
    public UserDTO get(Integer id) {
        return new UserDTO().setId(id)
                .setName("没有昵称:" + id)
                .setGender(id % 2 + 1); // 1 - 男;2 - 女
    }

}
  • 实现 UserRpcService 接口,提供 UserRpcService Dubbo 服务。

  • 注意,在类上添加了 Spring @Service 注解,暴露出 UserRpcServiceImpl Bean 对象。???? 后续,我们会将该 Bean 暴露成 UserRpcService Dubbo 服务,注册其到注册中心中,并提供相应的 Dubbo 服务。

2.2.4 Dubbo XML 配置文件

resources 目录下, 创建 dubbo.xml 配置文件,添加 Dubbo 的 Service 服务提供者,如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xmlns="http://www.springframework.org/schema/beans"
       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:service ref="userRpcServiceImpl" interface="cn.iocoder.springboot.lab30.rpc.api.UserRpcService"
        version="${dubbo.provider.UserRpcService.version}" />

</beans>
  • 使用 Dubbo 自定义的 Spring <dubbo:service> 标签,配置我们 「2.2.3 UserRpcServiceImpl」 成 UserRpcService 的 Dubbo 服务提供者。

更多 <dubbo:service> 标签的属性的说明,可见 《Dubbo 文档 —— dubbo:service》 。

2.2.5 ProviderApplication

创建 ProviderApplication 类,用于启动该项目,提供 Dubbo 服务。代码如下:

// ProviderApplication.java

@SpringBootApplication
@ImportResource("classpath:dubbo.xml")
public class ProviderApplication {

    public static void main(String[] args) {
        // 启动 Spring Boot 应用
        SpringApplication.run(ProviderApplication.class, args);
    }

}
  • 在类上,添加 @ImportResource 注解,引入 dubbo.xml 配置文件。

运行 #main(String[] args) 方法,启动项目。控制台打印日志如下:

// ... 省略其它日志

2019-12-01 22:40:34.721  INFO 64176 --- [pool-1-thread-1] .b.c.e.AwaitingNonWebApplicationListener :  [Dubbo] Current Spring Boot Application is await...
  • 看到该日志内容,意味着启动成功。

我们来使用 Zookeeper 客户端,查看 UserRpcService 服务是否注册成功。操作流程如下:

# 使用 Zookeeper 自带的客户端,连接到 Zookeeper 服务器
$ bin/zkCli.sh

# 查看 /dubbo 目录下的所有服务。
# 此时,我们查看到了 UserRpcService 服务
$ ls /dubbo
[cn.iocoder.springboot.lab30.rpc.api.UserRpcService]

# 查看 /dubbo/cn.iocoder.springboot.lab30.rpc.api.UserRpcService 目录下的存储情况。
# 此时,我们看到了 consumers 消费者信息,providers 提供者信息,routers 路由信息,configurators 配置信息。
$ ls /dubbo/cn.iocoder.springboot.lab30.rpc.api.UserRpcService
[consumers, configurators, routers, providers]

# 查看 UserRpcService 服务的节点列表
# 此时,可以看到有一个节点,就是我们刚启动的服务提供者。
$ ls /dubbo/cn.iocoder.springboot.lab30.rpc.api.UserRpcService/providers
[dubbo%3A%2F%2F10.171.1.115%3A20880%2Fcn.iocoder.springboot.lab30.rpc.api.UserRpcService%3Fanyhost%3Dtrue%
好的,以下是基于 Spring Cloud+Spring Boot+Nacos+Dubbo+mybatis plus+RocketMQ+Sentinel+Seata+mysql 搭建一个项目的步骤: 1. 首先,你需要安装并启动 Nacos 作为服务注册中心和配置中心。可以去官网下载最新版本的 Nacos,然后解压并启动即可。 2. 接下来,使用 Spring Initializr 创建一个基于 Spring Boot 的项目,并添加以下依赖: ``` <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-dubbo</artifactId> <exclusions> <exclusion> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-logging</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-alibaba-seata</artifactId> </dependency> <dependency> <groupId>com.alibaba.cloud</groupId> <artifactId>spring-cloud-starter-sentinel</artifactId> </dependency> <dependency> <groupId>org.apache.rocketmq</groupId> <artifactId>rocketmq-spring-boot-starter</artifactId> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> ``` 3. 配置 Nacos 作为服务注册中心和配置中心: ``` spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.server-addr=127.0.0.1:8848 spring.cloud.nacos.config.prefix=/config spring.cloud.nacos.config.file-extension=properties ``` 4. 配置 Dubbo: ``` spring.application.name=provider-service spring.dubbo.application.name=provider-service spring.dubbo.registry.address=nacos://127.0.0.1:8848 spring.dubbo.protocol.name=dubbo spring.dubbo.protocol.port=20880 ``` 5. 配置 RocketMQ: ``` spring.rocketmq.name-server=127.0.0.1:9876 spring.rocketmq.producer.group=producer-group spring.rocketmq.consumer.group=consumer-group ``` 6. 配置 Sentinel: ``` spring.cloud.sentinel.transport.dashboard=127.0.0.1:8080 ``` 7. 配置 Seata: ``` spring.cloud.alibaba.seata.tx-service-group=my_seata_tx_group spring.cloud.alibaba.seata.tx-service-mode=AT spring.cloud.alibaba.seata.config.type=nacos spring.cloud.alibaba.seata.config.nacos.server-addr=127.0.0.1:8848 spring.cloud.alibaba.seata.config.nacos.namespace=seata-dev ``` 8. 配置 MySQL 数据源: ``` spring.datasource.url=jdbc:mysql://localhost:3306/test?useUnicode=true&characterEncoding=UTF-8&useSSL=false spring.datasource.username=root spring.datasource.password=root spring.datasource.driver-class-name=com.mysql.jdbc.Driver ``` 9. 编写 Dubbo 服务接口和实现类: ``` public interface UserService { User getUserById(Long id); } @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Override public User getUserById(Long id) { return userDao.selectById(id); } } ``` 10. 配置 Dubbo 服务提供者: ``` @Configuration public class DubboConfig { @Reference private UserService userService; @Bean public ApplicationRunner runner() { return args -> { User user = userService.getUserById(1L); System.out.println(user); }; } } ``` 11. 编写 RocketMQ 生产者和消费者: ``` @Component public class MessageProducer { @Autowired private RocketMQTemplate rocketMQTemplate; public void send(String message) { rocketMQTemplate.convertAndSend("test-topic", message); } } @Component @RocketMQMessageListener(topic = "test-topic", consumerGroup = "test-consumer-group") public class MessageConsumer implements RocketMQListener<String> { @Override public void onMessage(String message) { System.out.println("Received message: " + message); } } ``` 12. 编写 MySQL 数据访问层: ``` @Mapper public interface UserDao extends BaseMapper<User> { } ``` 13. 使用 Seata 进行分布式事务控制: ``` @Service public class OrderServiceImpl implements OrderService { @Autowired private OrderDao orderDao; @GlobalTransactional @Override public void createOrder(Order order) { orderDao.insert(order); // 调用其他服务,可能会涉及到分布式事务操作 // ... } } ``` 14. 使用 Sentinel 进行服务限流和熔断: ``` @GetMapping("/hello") @SentinelResource(value = "hello", blockHandler = "helloBlockHandler") public String hello() { return "Hello World!"; } public String helloBlockHandler(BlockException ex) { return "Blocked by Sentinel: " + ex.getClass().getSimpleName(); } ``` 15. 最后,启动项目并测试各个功能是否正常运行。 以上就是基于 Spring Cloud+Spring Boot+Nacos+Dubbo+mybatis plus+RocketMQ+Sentinel+Seata+mysql 搭建一个项目的步骤。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值