跨境互联网 跨境互联网
首页
  • AI 工具

    • 绘图提示词工具 (opens new window)
    • ChatGPT 指令 (opens new window)
  • ChatGPT

    • ChatGP T介绍
    • ChatGPT API 中文开发手册
    • ChatGPT 中文调教指南
    • ChatGPT 开源项目
  • Midjourney

    • Midjourney 文档
  • Stable Diffusion

    • Stable Diffusion 文档
  • 其他

    • AIGC 热门文章
    • 账号合租 (opens new window)
    • 有趣的网站
  • Vue

    • Vue3前置
  • JAVA基础

    • Stream
    • Git
    • Maven
    • 常用第三方类库
    • 性能调优工具
    • UML系统建模
    • 领域驱动设计
    • 敏捷开发
    • Java 测试
    • 代码规范及工具
    • Groovy 编程
  • 并发编程&多线程

    • 并发编程
    • 高性能队列 Disruptor
    • 多线程并发在电商系统下的应用
  • 其他

    • 面试题
  • 消息中间中间件

    • Kafka
    • RabbitMQ
    • RocketMQ
  • 任务调度

    • Quartz
    • XXL-Job
    • Elastic-Job
  • 源码解析

    • Mybatis 高级使用
    • Mybatis 源码剖析
    • Mybatis-Plus
    • Spring Data JPA
    • Spring 高级使用
    • Spring 源码剖析
    • SpringBoot 高级使用
    • SpringBoot 源码剖析
    • Jdk 解析
    • Tomcat 架构设计&源码剖析
    • Tomcat Web应用服务器
    • Zookeeper 高级
    • Netty
  • 微服务框架

    • 分布式原理
    • 分布式集群架构场景化解决方案
    • Dubbo 高级使用
    • Dubbo 核心源码剖析
    • Spring Cloud Gateway
    • Nacos 实战应用
    • Sentinel 实战应用
    • Seata 分布式事务
  • 数据结构和算法的深入应用
  • 存储

    • 图和Neo4j
    • MongoDB
    • TiDB
    • MySQL 优化
    • MySQL 平滑扩容实战
    • MySQL 海量数据存储与优化
    • Elasticsearch
  • 缓存

    • Redis
    • Aerospike
    • Guava Cache
    • Tair
  • 文件存储

    • 阿里云 OSS 云存储
    • FastDF 文件存储
  • 基础

    • Linux 使用
    • Nginx 使用与配置
    • OpenResty 使用
    • LVS+Keepalived 高可用部署
    • Jekins
  • 容器技术

    • Docker
    • K8S
    • K8S
  • 01.全链路(APM)
  • 02.电商终极搜索解决方案
  • 03.电商亿级数据库设计
  • 04.大屏实时计算
  • 05.分库分表的深入实战
  • 06.多维系统下单点登录
  • 07.多服务之间分布式事务
  • 08.业务幂等性技术架构体系
  • 09.高并发下的12306优化
  • 10.每秒100W请求的秒杀架构体系
  • 11.集中化日志管理平台的应用
  • 12.数据中台配置中心
  • 13.每天千万级订单的生成背后痛点及技术突破
  • 14.红包雨的架构设计及源码实现
  • 人工智能

    • Python 笔记
    • Python 工具库
    • 人工智能(AI) 笔记
    • 人工智能(AI) 项目笔记
  • 大数据

    • Flink流处理框架
  • 加密区

    • 机器学习(ML) (opens new window)
    • 深度学习(DL) (opens new window)
    • 自然语言处理(NLP) (opens new window)
AI 导航 (opens new window)

Revin

首页
  • AI 工具

    • 绘图提示词工具 (opens new window)
    • ChatGPT 指令 (opens new window)
  • ChatGPT

    • ChatGP T介绍
    • ChatGPT API 中文开发手册
    • ChatGPT 中文调教指南
    • ChatGPT 开源项目
  • Midjourney

    • Midjourney 文档
  • Stable Diffusion

    • Stable Diffusion 文档
  • 其他

    • AIGC 热门文章
    • 账号合租 (opens new window)
    • 有趣的网站
  • Vue

    • Vue3前置
  • JAVA基础

    • Stream
    • Git
    • Maven
    • 常用第三方类库
    • 性能调优工具
    • UML系统建模
    • 领域驱动设计
    • 敏捷开发
    • Java 测试
    • 代码规范及工具
    • Groovy 编程
  • 并发编程&多线程

    • 并发编程
    • 高性能队列 Disruptor
    • 多线程并发在电商系统下的应用
  • 其他

    • 面试题
  • 消息中间中间件

    • Kafka
    • RabbitMQ
    • RocketMQ
  • 任务调度

    • Quartz
    • XXL-Job
    • Elastic-Job
  • 源码解析

    • Mybatis 高级使用
    • Mybatis 源码剖析
    • Mybatis-Plus
    • Spring Data JPA
    • Spring 高级使用
    • Spring 源码剖析
    • SpringBoot 高级使用
    • SpringBoot 源码剖析
    • Jdk 解析
    • Tomcat 架构设计&源码剖析
    • Tomcat Web应用服务器
    • Zookeeper 高级
    • Netty
  • 微服务框架

    • 分布式原理
    • 分布式集群架构场景化解决方案
    • Dubbo 高级使用
    • Dubbo 核心源码剖析
    • Spring Cloud Gateway
    • Nacos 实战应用
    • Sentinel 实战应用
    • Seata 分布式事务
  • 数据结构和算法的深入应用
  • 存储

    • 图和Neo4j
    • MongoDB
    • TiDB
    • MySQL 优化
    • MySQL 平滑扩容实战
    • MySQL 海量数据存储与优化
    • Elasticsearch
  • 缓存

    • Redis
    • Aerospike
    • Guava Cache
    • Tair
  • 文件存储

    • 阿里云 OSS 云存储
    • FastDF 文件存储
  • 基础

    • Linux 使用
    • Nginx 使用与配置
    • OpenResty 使用
    • LVS+Keepalived 高可用部署
    • Jekins
  • 容器技术

    • Docker
    • K8S
    • K8S
  • 01.全链路(APM)
  • 02.电商终极搜索解决方案
  • 03.电商亿级数据库设计
  • 04.大屏实时计算
  • 05.分库分表的深入实战
  • 06.多维系统下单点登录
  • 07.多服务之间分布式事务
  • 08.业务幂等性技术架构体系
  • 09.高并发下的12306优化
  • 10.每秒100W请求的秒杀架构体系
  • 11.集中化日志管理平台的应用
  • 12.数据中台配置中心
  • 13.每天千万级订单的生成背后痛点及技术突破
  • 14.红包雨的架构设计及源码实现
  • 人工智能

    • Python 笔记
    • Python 工具库
    • 人工智能(AI) 笔记
    • 人工智能(AI) 项目笔记
  • 大数据

    • Flink流处理框架
  • 加密区

    • 机器学习(ML) (opens new window)
    • 深度学习(DL) (opens new window)
    • 自然语言处理(NLP) (opens new window)
AI 导航 (opens new window)
  • 分布式原理

  • 分布式集群架构场景化解决方案
  • Dubbo

    • Dubbo高级使用

    • Dubbo核心源码剖析

      • Dubbo架构体系
      • Dubbo实战运用
        • 1 Dubbo与SpringBoot的整合
          • 1.1 工程POM依赖
          • 1.2 公用RPC接口工程
          • 1.3. 服务端工程
          • 1.4. 消费端工程
          • 1.5. 工程调用验证
        • 2 Dubbo高阶配置运用
          • 2.1 不同配置覆盖关系
          • 2.2 属性配置优先级
          • 2.3 重试与容错处理机制
          • 2.4 多版本控制
          • 2.5 本地存根调用
          • 2.6 负载均衡机制
          • 2.7 服务降级运用
          • 2.8 并发与连接控制
      • Dubbo SPI机制
      • 服务暴露(导出)与发现
      • Dubbo高可用集群
      • 网络通信原理
  • SpringCloud

  • SpringCloudAlibaba

  • 微服务框架
  • Dubbo
  • Dubbo核心源码剖析
Revin
2023-07-22
目录

Dubbo实战运用

# 1 Dubbo与SpringBoot的整合

基于Zookeeper实现Dubbo与Spring Boot的集成整合。

# 1.1 工程POM依赖

    <properties>
        <dubbo-version>2.7.8</dubbo-version>
        <spring-boot.version>2.3.0.RELEASE</spring-boot.version>
    </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>


            <!-- Apache Dubbo  -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-dependencies-bom</artifactId>
                <version>${dubbo-version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>


            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo</artifactId>
                <version>${dubbo-version}</version>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework</groupId>
                        <artifactId>spring</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>javax.servlet</groupId>
                        <artifactId>servlet-api</artifactId>
                    </exclusion>
                    <exclusion>
                        <groupId>log4j</groupId>
                        <artifactId>log4j</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <dependencies>
        <!-- Dubbo Spring Boot Starter -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-spring-boot-starter</artifactId>
            <version>${dubbo-version}</version>
        </dependency>
        <!-- Dubbo核心组件 -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo</artifactId>
        </dependency>
        <!--Spring Boot 依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
            <version>${spring-boot.version}</version>
        </dependency>
        <!-- Zookeeper客户端框架 -->
        <dependency>
            <groupId>org.apache.curator</groupId>
            <artifactId>curator-framework</artifactId>
            <version>4.0.1</version>
        </dependency>
        <!-- Zookeeper dependencies -->
        <dependency>
            <groupId>org.apache.dubbo</groupId>
            <artifactId>dubbo-dependencies-zookeeper</artifactId>
            <version>${dubbo-version}</version>
            <type>pom</type>
            <exclusions>
                <exclusion>
                    <groupId>org.slf4j</groupId>
                    <artifactId>slf4j-log4j12</artifactId>
                </exclusion>
            </exclusions>
        </dependency>
    </dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87

Dubbo采用2.7.8版本, Spring Boot采用的是2.3.0.RELEASE版本。

如果依赖下载出现问题, 可以指定具体的仓库:

<repositories>
    <repository>
        <id>apache.snapshots.https</id>
        <name>Apache Development Snapshot Repository</name>
        <url>https://repository.apache.org/content/repositories/snapshots</url>
        <releases>
            <enabled>false</enabled>
        </releases>
        <snapshots>
            <enabled>true</enabled>
        </snapshots>
    </repository>
</repositories>
1
2
3
4
5
6
7
8
9
10
11
12
13

# 1.2 公用RPC接口工程

为便于客户端与服务端的RPC接口引用, 这里对RPC接口做统一封装。

image-20210118150734301

定义了一个订单服务接口, 用于测试验证。

public interface OrderService {


    /**
     * 获取订单详情
     * @param orderId
     * @return
     */
    String getOrder(Long orderId);
}


1
2
3
4
5
6
7
8
9
10
11
12

# 1.3. 服务端工程

  1. 工程结构

image-20210118151028959

  1. POM依赖

        <dependencies>
            <!-- Dubbo Spring Boot Starter -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>${dubbo-version}</version>
            </dependency>
            <!-- Dubbo 核心依赖 -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo</artifactId>
            </dependency>
            <!-- 公用RPC接口依赖 -->
            <dependency>
                <groupId>com.itheima</groupId>
                <artifactId>dubbo-spring-interface</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
  2. RPC服务接口

    @DubboService(version = "${dubbo.spring.provider.version}")
    public class OrderServiceImpl implements OrderService {
    
    
        /**
         * 服务端口
         */
        @Value("${server.port}")
        private String serverPort;
        
        @Value("${dubbo.spring.provider.version}")
        private String serviceVersion;
    
    
        /**
         * 获取订单详情
         * @param orderId
         * @return
         */
        public String getOrder(Long orderId) {
    
    
           String result = "get order detail ,orderId="+orderId +",serverPort="+serverPort +",serviceVersion="+serviceVersion;
            System.out.println(result);
            return result;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27

    通过DubboService注解, 声明为RPC服务,version可以标识具体的版本号, 消费端需匹配保持一致。

  3. 工程配置

    # 服务端口
    server.port=18081
    # 应用程序名称
    spring.application.name=dubbo-spring-provider
    # Dubbo服务扫描路径
    dubbo.scan.base-packages=com.itheima
    
    
    # Dubbo 通讯协议
    dubbo.protocol.name=dubbo
    # Dubbo服务提供的端口, 配置为-1,代表为随机端口 默认20880
    dubbo.protocol.port=-1
    
    
    ## Dubbo 注册器配置信息
    dubbo.registry.address=zookeeper://127.0.0.1:2181
    dubbo.registry.file = ${user.home}/dubbo-cache/${spring.application.name}/dubbo.cache
    dubbo.spring.provider.version = 1.0.0
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
  4. Spring Boot启动程序

    @SpringBootApplication
    @ComponentScan(basePackages = {"com.itheima"})
    public class DubboSpringProviderApplication {
    
    
        public static void main(String[] args) {
            SpringApplication.run(DubboSpringProviderApplication.class, args);
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

# 1.4. 消费端工程

  1. 工程结构

image-20210118152430725

  1. POM依赖:

        <dependencies>
            <!-- Dubbo Spring Boot Starter -->
            <dependency>
                <groupId>org.apache.dubbo</groupId>
                <artifactId>dubbo-spring-boot-starter</artifactId>
                <version>${dubbo-version}</version>
            </dependency>
            <!-- 公用RPC接口依赖 -->
            <dependency>
                <groupId>com.itheima</groupId>
                <artifactId>dubbo-spring-interface</artifactId>
                <version>${project.version}</version>
            </dependency>
        </dependencies>
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  2. 消费端调用

    @Controller
    @RequestMapping("/order")
    public class OrderController {
    
    
        private final Logger logger = LoggerFactory.getLogger(getClass());
    
    
    
    
        /**
         * 订单服务接口
         */
        @DubboReference(version = "${dubbo.spring.provider.version}")
        private OrderService orderService;
    
    
        /**
         * 获取订单详情接口
         * @param orderId
         * @return
         */
        @RequestMapping("/getOrder")
        @ResponseBody
        public String getOrder(Long orderId) {
            String result = null;
            try {
                result = orderService.getOrder(orderId);
            }catch(Exception e) {
                logger.error(e.getMessage(), e);
            }
            return result;
        }
    
    
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
  3. 工程配置

    # 服务端口
    server.port=18084
    #服务名称
    spring.application.name=dubbo-spring-consumer
    #服务版本号
    dubbo.spring.provider.version = 1.0.0
    #消费端注册器配置信息
    dubbo.registry.address=zookeeper://127.0.0.1:2181
    dubbo.registry.file = ${user.home}/dubbo-cache/${spring.application.name}/dubbo.cache
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
  4. Spring Boot启动程序

    @SpringBootApplication
    @ComponentScan(basePackages = {"com.itheima"})
    public class DubboSpringConsumerApplication {
    
    
        public static void main(String[] args) {
            SpringApplication.run(DubboSpringConsumerApplication.class, args);
        }
    }
    
    
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11

# 1.5. 工程调用验证

  1. 启动ZK注册中心

  2. 启动服务端, 运行DubboSpringProviderApplication

  3. 启动消费端, 运行DubboSpringConsumerApplication

  4. 请求获取订单接口, 地址: http://127.0.0.1:18084/order/getOrder?orderId=1001

    调用成功:

    image-20210119091447916

# 2 Dubbo高阶配置运用

# 2.1 不同配置覆盖关系

关于配置参看官方文档:https://dubbo.apache.org/zh/docsv2.7/user/configuration/

演示:

1、通过ProviderConfig配置全局超时(可通过yml配置覆盖)

2、在@DubboService注解上配置接口超时

3、在@DubboService注解上配置接口方法超时

4、在消费方进行配置,查看覆盖情况

  1. 覆盖规则: img配置规则:

    • 方法级优先,接口级次之,全局配置再次之。
    • 如果级别一样,则消费方优先,提供方次之。
  2. 服务端超时设定

    增加配置类:

    @Configuration
    public class DubboCustomConfig {
    
    
        /**
         *  服务端
         * @return
         */
        @Bean
        public ProviderConfig registryConfig() {
            ProviderConfig providerConfig = new ProviderConfig();
            // 设定超时时间为5S
            providerConfig.setTimeout(5000);
            return providerConfig;
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16

    修改服务接口实现:

    设定模拟睡眠时间

        /**
         * 获取订单详情
         * @param orderId
         * @return
         */
        public String getOrder(Long orderId) {
            try {
                // 休眠1.5秒
                Thread.sleep(1500L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Get Order Detail, Id: " + orderId + ", serverPort: " + serverPort;
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
  3. 客户端调用验证

    http://127.0.0.1:18084/order/getOrder?orderId=123

    • 服务端全局超时设为2秒(不触发超时), 消费端设定超时时间为1秒(触发超时)。

      修改调用代码:

          /**
           * 订单服务接口
        */
          @DubboReference(version = "${dubbo.spring.provider.version}", timeout = 1000)
       private OrderService orderService;
      
      1
      2
      3
      4
      5

      调用结果, 触发超时:

      image-20210119111615122

      表明消费端配置优先。

    • 服务端全局超时设定为1秒(触发超时), 消费端去掉超时时间配置。

      image-20210119111947521

      触发超时, 表明服务提供方优先级次之。

# 2.2 属性配置优先级

  1. 优先级规则 img

    优先级从高到低:

    • JVM -D 参数;

      -Ddubbo.protocol.port=20881
      
      1
    • XML(application.yml/application.properties)配置会重写 dubbo.properties 中的,一般配置项目特有的

      dubbo:
        protocol:
          name: dubbo # 通讯协议
          #port: 20880   # dubbo服务提供方的端口,该值是默认值
          port: 20882
      
      1
      2
      3
      4
      5
    • Properties默认配置(dubbo.properties),仅仅作用于以上两者没有配置时,一般配置全局公共配置

      dubbo.protocol.port=20883
      
      1
  2. JVM参数优先级验证

    • application.properties里面配置了dubbo.protocol.port端口10888

    • JVM运行参数端口设定为-Ddubbo.protocol.port=10889

      image-20210119123627518

    • 启动服务

      image-20210119123708541

      服务启动完成, 可以看到端口优先以JVM参数为准。

  3. Properties配置文件验证

    • 注释掉application.properties里面配置的dubbo.protocol.name和dubbo.protocol.port配置

    • dubbo.properties里面配置dubbo.protocol.name和dubbo.protocol.port

    • 在启动参数里, 添加-Ddubbo.properties.file=dubbo.properties

      image-20210120141300832

    • 启动服务

      查看dubbo.properties配置的端口, 可以看到正常生效:

      C:\Users\hxx68>netstat -ano |findstr 30889
        TCP    0.0.0.0:30889          0.0.0.0:0              LISTENING       49816
        TCP    [::]:30889             [::]:0                 LISTENING       49816
      
      1
      2
      3

# 2.3 重试与容错处理机制

  1. 容错机制:

    • Failfast Cluster

      快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

    • Failsafe Cluster

      失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

    • Failback Cluster

      失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。

    • Forking Cluster

      并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。

    • Broadcast Cluster

      广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。

    后面章节还会对其原理做详细讲解。

  2. 调整客户端重试次数

        /**
         * 订单服务接口
         */
        @DubboReference(version = "${dubbo.spring.provider.version}",retries = 3)
        private OrderService orderService;
    
    1
    2
    3
    4
    5

    这里的重试次数设定为3次。

  3. 修改服务端超时时间

    模拟超时, 让客户端触发重试。

        /**
         *  服务端全局配置
         * @return
         */
        @Bean
        public ProviderConfig registryConfig() {
            ProviderConfig providerConfig = new ProviderConfig();
            providerConfig.setTimeout(1000);
            return providerConfig;
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10

    将超时时间设小一些为1秒。

  4. 客户端调用(单个服务)

    http://127.0.0.1:18084/order/getOrder?orderId=123

    查看服务端控制台,可以看到触发重试机制:

    image-20210120154534252

    加上第一次的调用和3次重试, 共4次。

  5. 客户端调用(多个,涉及到负载均衡机制,后面再测试)

允许多个实例运行, 开启多个服务

访问接口, http://127.0.0.1:18084/order/getOrder?orderId=123

image-20210120172904281

第一个服务实例,访问两次, 其他每个服务访问一次。

# 2.4 多版本控制

  1. 启动三个服务端

    第一个服务端版本为1.0.0, 第二、三个服务端版本分别为:2.0.0 和 3.0.0

    主要是修改application.properties配置:

    #服务版本号
    dubbo.spring.provider.version = 2.0.0
    
    1
    2
  2. 启动三个服务提供者,通过-Ddubbo.spring.provider.version = 2.0.0 -Dserver.port=18082来启动三个

    相关的端口不能重复

  3. 消费端指定版本号

    同样修改application.properties配置:

    #服务版本号
    dubbo.spring.provider.version = 2.0.0
    
    1
    2

    仍然通过-Ddubbo.spring.provider.version = 2.0.0来调用不同版本的服务

    测试时,注释掉超时的代码

  4. 仍是采用超时配置, 通过重试测试验证

    测试验证结果:

    请求只会访问至版本号为2.0.0的服务节点上面。

# 2.5 本地存根调用

  1. 实现流程

    /user-guide/images/stub.jpg

    把 Stub 暴露给用户,Stub 可以决定要不要去调 Proxy。

  2. 客户端存根实现:

    增加service接口

    public class OrderServiceStub implements OrderService {
    
    
        private final OrderService orderService;
    
    
        // 构造函数传入真正的远程代理对象
        public OrderServiceStub(OrderService orderService){
            this.orderService = orderService;
        }
    
    
        /**
         * 获取订单详情
         * @param orderId
         * @return
         */
        public String getOrder(Long orderId){
            // 在客户端执行, 预先验证参数是否合法,等等
            try {
                if(null != orderId) {
                    return orderService.getOrder(orderId);
                }
                return "参数校验错误!";
            } catch (Exception e) {
                //容错处理
                return "出现错误:" + e.getMessage();
            }
        }
    }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
  3. 修改客户端调用配置

        /**
         * 订单服务接口
         */
        @DubboReference(version = "${dubbo.spring.provider.version}",retries = 3, stub = "com.itheima.dubbo.spring.consumer.service.OrderServiceStub")
        private OrderService orderService;
    
    
    
    1
    2
    3
    4
    5
    6
    7

    stub要配置存根接口的完整路径。

  4. 测试调用

    访问不带参数的地址: http://127.0.0.1:18084/order/getOrder

    image-20210120211601398

    会进入存根接口的处理逻辑, 提示校验异常。

# 2.6 负载均衡机制

  1. 默认负载策略

    Dubbo默认采用的是随机负载策略。

    开启三个服务节点,通过消费端访问验证: http://127.0.0.1:18084/order/getOrder?orderId=123

    通过控制后台日志输出, 可以看到每个服务节点呈现不规则的调用。

  2. Dubbo 支持的负载均衡策略,可用参看源码:AbstractLoadBalance

    • Random LoadBalance:默认

      随机,按权重设置随机概率。 在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

    • RoundRobin LoadBalance

      加权轮询负载均衡,按公约后的权重设置轮询比率。 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

    • LeastActive LoadBalance

      最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。 活跃数其实就是在当前这个服务调用者中当前这个时刻 某个invoker(某个服务提供者的某个接口)某个方法的调用并发数,在调用之前+1 调用之后-1的一个计数器,如果出现多个活跃数相等invoker的时候使用随机算法来选取一个

    • ConsistentHash LoadBalance

      一致性 Hash,相同参数的请求总是发到同一提供者。 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

一致性Hash负载均衡涉及到两个主要的配置参数为hash.arguments 与hash.nodes。

hash.arguments : 当进行调用时候根据调用方法的哪几个参数生成key,并根据key来通过一致性hash算法来选择调用结点

hash.nodes: 为结点的副本数

  • ShortestResponseLoadBalance

    2.7.7 +新增

    最短响应时间负载均衡

    从多个服务提供者中选择出调用成功的且响应时间最短的服务提供者,由于满足这样条件的服务提供者有可能有多个。所以当选择出多个服务提供者后要根据他们的权重做分析,如果权重一样,则随机

    源码实现: org.apache.dubbo.rpc.cluster.loadbalance.AbstractLoadBalance

    Dubbo提供了四种实现:

image-20210120224612307

  1. 四种配置方式:

    优先级从下至上:

    • 服务端的服务级别:

      <dubbo:service interface="..." loadbalance="roundrobin" />
      
      1
    • 客户端的服务级别:

      <dubbo:reference interface="..." loadbalance="roundrobin" />
      
      1

      注意:服务提供者配置后最终也只是同步到消费者端。故一般在消费端配置

    • 服务端方法级别:

      <dubbo:service interface="...">
          <dubbo:method name="..." loadbalance="roundrobin"/>
      </dubbo:service>
      
      1
      2
      3
    • 客户端方法级别:

      <dubbo:reference interface="...">
          <dubbo:method name="..." loadbalance="roundrobin"/>
      </dubbo:reference>
      
      1
      2
      3

      当然这里还有全局配置(略),

  2. 调用验证

    修改客户端的负载策略, 改为轮询策略:

    注意很多配置都有三个级别,针对方法的,针对接口的,全局的。

    @DubboReference(version = "${dubbo.spring.provider.version}",retries = 3,
                loadbalance = "roundrobin",
                stub = "com.itheima.dubbo.spring.consumer.service.OrderServiceStub")
    
    1
    2
    3

    开启三个服务节点, 进行访问验证: http://127.0.0.1:18084/order/getOrder?orderId=123

    会依次轮询进行调用。

​ 注意:测试时将服务提供者的版本号都调成一致(1.0.0),超时配置注释掉!

  1. 动态权重调整验证

    管理后台地址: http://127.0.0.1:8080/#

    通过管理后台修改服务的权重配置:

    image-20210121002014163

    将两台节点的权重降低至20:

    image-20210121002111548

    调整后可以看到权重配置已经生效:

    image-20210121002143413

    通过消费者接口访问, 会发现第一台权重较大的节点, 访问次数会明显增多。

# 2.7 服务降级运用

  1. 服务动态禁用

    启动单个服务节点,进入Dubbo Admin, 创建动态配置规则:

    configVersion: v2.7
    enabled: true
    configs:
      - side: provider
        addresses:
          - '0.0.0.0:20880'
        parameters:
          timeout: 3000
          disabled: true
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    将disabled属性设为true, 服务禁用, 可以错误提示:

    image-20210121105502289

    将disabled属性改为false,

    configVersion: v2.7
    enabled: true
    configs:
      - side: provider
        addresses:
          - '0.0.0.0:20880'
        parameters:
          timeout: 3000
          disabled: false
    
    1
    2
    3
    4
    5
    6
    7
    8
    9

    恢复正常访问:

    image-20210121105637124

  2. 服务降级

    • 配置规则

      RegistryFactory registryFactory = ExtensionLoader.getExtensionLoader(RegistryFactory.class).getAdaptiveExtension();
      Registry registry = registryFactory.getRegistry(URL.valueOf("zookeeper://10.20.153.10:2181"));
      registry.register(URL.valueOf("override://0.0.0.0/com.foo.BarService?category=configurators&dynamic=false&application=foo&mock=force:return+null"));
      
      1
      2
      3
      • mock=force:return+null 表示消费方对该服务的方法调用都直接返回 null 值,不发起远程调用。用来屏蔽不重要服务不可用时对调用方的影响。
      • 还可以改为 mock=fail:return+null表示消费方对该服务的方法调用在失败后,再返回 null 值,不抛异常。用来容忍不重要服务不稳定时对调用方的影响。
    • 降级测试(force方式)

      进入Dubbo Admin进行配置:

      configVersion: v2.7
      enabled: true
      configs:
        - side: consumer
          addresses:
            - 0.0.0.0
          parameters:
            timeout: 3000
            mock: 'force:return null'
      
      
      
      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11

      客户端调用, 会直接屏蔽, 并且服务端控制台不会有任何调用记录:

      image-20210121165217882

    • 降级测试(fail方式)

      进入Dubbo Admin配置:

      configVersion: v2.7
      enabled: true
      configs:
        - side: consumer
          addresses:
            - 0.0.0.0
          parameters:
            timeout: 1000
            mock: 'fail:return null'
      
      1
      2
      3
      4
      5
      6
      7
      8
      9

      这里为了触发调用异常, 超时时间缩短为1秒。

      注意这里的超时时间可能不会起作用,最终的超时时间还是得看项目中配置,故在服务提供方将线程休眠时间延长,造成调用超时。

      客户端调用, 会出现降级显示为空:

      image-20210121165544731

      同时服务端会有调用记录显示(请求会进入服务端,但由于超时, 调用是失败):

      image-20210121165617267

# 2.8 并发与连接控制

实际运用, 会碰到高并发与峰值场景, Dubbo是可以做到并发与连接数控制。

可使用jmeter进行测试!

并发数控制

  1. 服务端控制

    • 服务级别

      <dubbo:service interface="com.foo.BarService" executes="10" />
      
      1

      服务器端并发执行(或占用线程池线程数)不能超过 10 个。

    • 方法级别

      <dubbo:service interface="com.foo.BarService">
          <dubbo:method name="sayHello" executes="3" />
      </dubbo:service>
      
      1
      2
      3

      限制具体的方法,服务器端并发执行(或占用线程池线程数)不能超过3 个。

  2. 客户端控制

    • 调用的服务控制

      <dubbo:reference interface="com.foo.BarService" actives="10" />
      
      1

      每客户端并发执行(或占用连接的请求数)不能超过 10 个。

    • 调用的服务方法控制

      <dubbo:reference interface="com.foo.BarService">
          <dubbo:method name="sayHello" actives="10" />
      </dubbo:service>
      
      1
      2
      3

      dubbo:reference比dubbo:service优先。

  3. 客户端负载配置

    <dubbo:reference interface="com.foo.BarService" loadbalance="leastactive" />
    
    1

    负载策略为最小连接数时, Loadbalance 会调用并发数最小的 Provider。

连接数控制

  1. 服务端连接控制

    <dubbo:provider protocol="dubbo" accepts="10" />
    
    1

    限制服务器端接受的连接不能超过 10 个

  2. 客户端连接控制

    <dubbo:reference interface="com.foo.BarService" connections="10" />
    
    1

    限制客户端服务使用连接不能超过 10 个

    如果 dubbo:service 和 dubbo:reference 都配了 connections,dubbo:reference 优先。

上次更新: 2025/04/03, 11:07:08
Dubbo架构体系
Dubbo SPI机制

← Dubbo架构体系 Dubbo SPI机制→

最近更新
01
tailwindcss
03-26
02
PaddleSpeech
02-18
03
whisper
02-18
更多文章>
Theme by Vdoing | Copyright © 2019-2025 跨境互联网 | 豫ICP备14016603号-5 | 豫公网安备41090002410995号
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式