SpringCloud学习2(Spring Cloud Netflix)负载均衡Ribbon、Feign负载均衡、Hystix服务熔断

文章目录

  • 负载均衡Ribbon
    • Ribbon的作用
    • 代码实现
      • 生产者cloud1_provider实现
        • 配置文件
        • 在HiController中编写以下代码
        • 启动集群
      • 消费者cloud1_consumer实现
        • 引入依赖
        • 编写配置文件
        • 编写启动类,并给RestTemplate配置@LoadBalanced注解
        • 编写RestController来测试
  • Feign负载均衡
    • 简介Feign
    • Feign集成了RIbbon
    • 编码测试(基于cloud1_consumer项目修改)
      • 引入依赖
      • 启用FeignClient
      • 编写FeignService接口
      • 编写Controller测试使用
  • Hystrix服务熔断
    • 分布式系统面临问题——服务雪崩
    • 什么是Hystrix断路器
    • 作用:
      • 服务熔断`@HystrixCommand`
      • 服务熔断与服务降级
      • 服务熔断代码案例
        • 引入依赖
        • 启用断路器
        • 编写带有短路方法的测试Controller
      • 服务降级代码案例(基于之前搭建的cloud1_consumer项目修改)
        • 引入依赖
        • 编写yml配置
        • 编写Feign接口
        • 编写降级回调工厂类 OrderServiceFallBackFactory
        • 编写测试Controller
    • Hystrix流监控Dashboard
      • 代码案例
        • 生产侧,被监测方依赖配置与代码
      • 监控客户端依赖配置与代码cloud1_hystrix_dashboard

负载均衡Ribbon

SpringCloudRibbon是基于NetflixRibbon实现的一套客户端负载均衡工具。主要功能是提供客户端的负载均衡算法。Ribbon客户端提供系列完整的配置,如连接超市,重试机制。简单说就是在配置文件中列出LoadBalancer后面的所有机器。Ribbon会自动帮助基于某种规则(轮询、随机)去连接机器。

Ribbon的作用

  • LB(Load Balance)负载均衡,在微服务或分布式集群中常用的一种应用
  • 负载均衡简单来说就是平摊用户请求到多个赴俄乌,从而达到系统的HA(高可用)
  • 常见负载均衡软件Nginx、LVS
  • Dubbo、SpringCloud中均给我们提供了负载均衡。SpringCloud负载均衡算法可以自定义
  • 负载均衡简单分类
    • 集中式Load Balance
      • 即在服务端消费方和提供方之间使用独立的LB设施,如Nginx,由该服务负责把访问请求通过负载策略转发到服务提供方
      • 进程式Load Balance
        • 将LB的逻辑集成到消费者,消费者从服务注册中心获取到有哪些地址可用,然后自己再根据这些地址选举出一个合适的服务器。
        • Ribbon就属于进程式LB,他是一个类库。集成于消费者进程,消费者通过它来获取到服务提供者的地址。

代码实现

基于前面的代码来改造服务提供者的代码,先搭建服务提供者的集群

生产者cloud1_provider实现

配置文件

spring:
  profiles:
    active: dev-9991

---
server:
  port: 9991
spring:
  config:
    activate:
      on-profile: dev-9991
  application:
    name: cloud1-provider
logging:
  level:
    com.hx: debug
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8881/eureka/,http://localhost:8882/eureka/
  instance:
    instance-id: cloud-prod-1
    #    配置主机地址
    hostname: localhost

---
server:
  port: 9992
spring:
  config:
    activate:
      on-profile: dev-9992
  application:
    name: cloud1-provider
logging:
  level:
    com.hx: debug
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8881/eureka/,http://localhost:8882/eureka/
  instance:
    instance-id: cloud-prod-2
    #    配置主机地址
    hostname: localhost

在HiController中编写以下代码

@Value("${server.port}")
private String port;

@RequestMapping("/")
public String hi() {
    return "<h1>HI Spring Cloud 1  " + port + "</h1>";
}

启动集群

在这里插入图片描述

消费者cloud1_consumer实现

引入依赖

注意:这里不需要重复引入ribbon的依赖,否则无法ribbon将获取不到实例

<?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>
        <artifactId>cloud1_parent</artifactId>
        <groupId>com.hx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>
    <artifactId>cloud1_consumer</artifactId>
    <name>cloud1_consumer</name>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>com.hx</groupId>
            <artifactId>cloud1_api</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </dependency>
    </dependencies>
</project>

编写配置文件

server:
  port: 7771
spring:
  application:
    name: cloud1-consumer
logging:
  level:
    com.hx: debug
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8881/eureka/,http://localhost:8882/eureka/
    register-with-eureka: false   # 消费者不需要注册自己
  instance:
    instance-id: cloud-prod-1
    #    配置主机地址
    hostname: localhost

编写启动类,并给RestTemplate配置@LoadBalanced注解

@SpringBootApplication
@EnableEurekaClient
public class Cloud1ConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(Cloud1ConsumerApp.class,args);
    }
    // 配置负载均衡的restTemplate
    @Bean
    @LoadBalanced       // ribbon
    public RestTemplate restTemplate(){
        return new RestTemplate();
    }
}

编写RestController来测试

@RestController
public class RestOrderController {
    @Autowired
    private RestTemplate restTemplate;

    private static final String ORDER_APP_URI = "http://CLOUD1-PROVIDER";

    @RequestMapping("/")
    public String index() {
        return restTemplate.getForObject(ORDER_APP_URI.concat("/"), String.class);
    }

    @RequestMapping("/restOrder")
    public Order getOrder() {
        return restTemplate.getForObject(ORDER_APP_URI.concat("/getOrder"), Order.class);
    }
}

Feign负载均衡

简介Feign

Feign是声明式的web service客户端。让微服务之间的调用更简单,类似controller调用service。SpringCloud继承了Ribbon和Eureka,可以在使用Feign时提供负载均衡的http客户端。Feign旨在使得编写JavaHttp客户端简单容易。
只需要给一个接口,然后添加注解就可以。

Feign集成了RIbbon

利用Ribbon维护了微服务列表信息,通过轮询实现了客户端的负载均衡,而与Ribbon不同的是,通过Feign只需要定义服务绑定接口,且以声明式的方法,优雅简单的实现服务调用。

编码测试(基于cloud1_consumer项目修改)

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-feign</artifactId>
    <version>1.4.7.RELEASE</version>
</dependency>

启用FeignClient

@SpringBootApplication
@EnableEurekaClient
//@EnableFeignClients
@EnableFeignClients(basePackages = "com.hx.service")
public class Cloud1ConsumerApp {
    public static void main(String[] args) {
        SpringApplication.run(Cloud1ConsumerApp.class, args);
    }

    // 配置负载均衡的restTemplate
    @Bean
    @LoadBalanced       // ribbon
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

编写FeignService接口

@Service
@FeignClient(value = "CLOUD1-PROVIDER")
public interface RestOrderService {

    @GetMapping("/")
    String index();

    @PostMapping("/getOrder")
    Order restGetOrder();
}

编写Controller测试使用

@RestController
@RequestMapping("/fg")
public class RestOrderFeignController {
    @Autowired
    private RestOrderService restOrderService;

    @RequestMapping("/")
    public String index() {
        return restOrderService.index();
    }

    @RequestMapping("/restOrder")
    public Order getOrder() {
        return restOrderService.restGetOrder();
    }
}

Hystrix服务熔断

分布式系统面临问题——服务雪崩

复杂分布式体系结构中应用程序有数十个依赖关系,每个依赖关系在某些时刻不可避免的失败。
多个微服务之间调用的时候,假设A服务调用B、C服务,微服务B和C又调用其他微服务,这就是所谓的"扇出"。如果扇出的链路上某个微服务的调用响应超市或时间过长无响应,对微服务A的调用就会占用越来越多的系统资源,进而引发系统崩溃,即服务雪崩。
对于高流量应用,单一的后端依赖可能导致所有服务上的所有资源都在几十秒内饱和。更糟糕的是这些应用还可能导致服务之间的延迟增加,备份队列,线程和其他系统资源紧张,导致整个系统发生更多的级联腹胀。这些都表示需要对故障和延迟进行隔离和管理,以便单个依赖关系的失败,不取消整个应用程序系统。

什么是Hystrix断路器

Hystrix是一个应用于处理分布式系统的延迟和容错开源库,在分布式系统中,许多依赖不可避免的调用失败,eg:超时、异常等。Hystrix能够保证在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,提高分布式系统的弹性。
断路器本身是一种开关,当某个服务单元发生故障后,通过断路器的故障监控,向服务调用方返回一个服务预期的、可处理的备选响应,而不是长时间的等待或者抛出无法处理的异常,这样保证了服务调用方的线程不会被长时间占用。从而避免故障在分布式系统中的蔓延乃至雪崩。

作用:

服务降级、服务熔断、服务限流、接近实时监控

服务熔断@HystrixCommand

熔断机制是应对雪崩问题的一种微服务链路保护机制。
当扇出的某个微服务不可用或者响应时间太长,会进行服务降级,进而熔断该节点微服务调用,快速返回错误的相应细腻些。当检测到该服务响应正常后,恢复链路调用。在SpringCloud熔断机制通过Hystrix实现。Hystrix会监控微服务间调用的状况,当失败的调用到达一定阈值,缺省5s内20次失败就会启动熔断机制。

服务熔断与服务降级

服务熔断(服务端编写):某个服务超时或者异常,引起熔断
服务降级(客户端编写):从整体的网站请求负载考虑,当某个服务熔断或者关闭后服务将不再被调用。此时在客户端可以准备一个失败回调FallbackFactory。返回一个默认的缺省值,整体服务水平下降。

服务熔断代码案例

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    <version>2.1.0.RELEASE</version>
</dependency>

启用断路器

@SpringBootApplication
@EnableDiscoveryClient  // 服务发现,不只是eureka
//@EnableCircuitBreaker   // 启用断路器Hystrix
@EnableHystrix
public class Cloud1ProdApp {
    public static void main(String[] args) {
        SpringApplication.run(Cloud1ProdApp.class);
    }
}

编写带有短路方法的测试Controller

@RestController
@RequestMapping("hystrix")
public class Hi_HystrixController {
    @Autowired
    private OrderService orderService;

    @HystrixCommand(fallbackMethod = "getOrderHystrix")
    @RequestMapping("/order")
    public Order getOrder(String id) {
        if(StringUtils.isBlank(id)){
            throw new RuntimeException("参数ID不可以为空!");
        }
        return orderService.getOrder(id);
    }

    /**
     * 注意:这个熔断的方法,里的参数列表要和上面的方法参数列表相同
     * 否则报错:com.netflix.hystrix.contrib.javanica.exception.FallbackDefinitionException: fallback method wasn't found
     */
    public Order getOrderHystrix(String id) {
        id = UUID.randomUUID().toString();
        return orderService.getOrder(id).setId("请传入正确的ID");
    }
}

服务降级代码案例(基于之前搭建的cloud1_consumer项目修改)

引入依赖

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

编写yml配置

feign:
  hystrix:
    enable: true

编写Feign接口

@Service
@FeignClient(value = "CLOUD1-PROVIDER",fallbackFactory = OrderServiceFallBackFactory.class)
public interface RestOrderService {

    @GetMapping("/")
    String index();

    @PostMapping("/getOrder")
    Order restGetOrder();
 	// 我们这次测试的接口   
    @PostMapping("/hystrix/order")
    Order restGetOrderFall();
}

编写降级回调工厂类 OrderServiceFallBackFactory

@Component
public class OrderServiceFallBackFactory implements FallbackFactory<RestOrderService> {
    @Override
    public RestOrderService create(Throwable cause) {
        return new RestOrderService() {
            @Override
            public String index() {
                return "降级";
            }

            @Override
            public Order restGetOrder() {
                return null;
            }
            @Override
            public Order restGetOrderFall() {
                return new Order().setId("没有找到,可能是未传入ID")
                        .setCreateTime(SimpleDateFormat.getDateTimeInstance().format(new Date()));
            }
        };
    }
}

编写测试Controller

@RestController
@RequestMapping("/fgfall")
public class RestOrderFeignController2 {
    @Autowired
    private RestOrderService restOrderService;

    @RequestMapping("/order2")
    public Order getOrder() {
        return restOrderService.restGetOrderFall();
    }
}

注意:这里高版本的springcloud2021版本不清楚为什么无法实现

Hystrix流监控Dashboard

在这里插入图片描述

代码案例

生产侧,被监测方依赖配置与代码

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>
#暴露全部的监控信息
management:
  endpoints:
    web:
      exposure:
        include: "*"
@Bean
public ServletRegistrationBean hystrixMetricsStreamServlet(){
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
    registrationBean.setLoadOnStartup(1);
    registrationBean.addUrlMappings("/actuator/hystrix.stream");
    registrationBean.setName("HystrixMetricsStreamServlet");
    return registrationBean;
}

监控客户端依赖配置与代码cloud1_hystrix_dashboard

<?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>
        <artifactId>cloud1_parent</artifactId>
        <groupId>com.hx</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>cloud1_hystrix_dashboard</artifactId>
    <name>cloud1_hystrix_dashboard</name>

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

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>
    </dependencies>
</project>
package com.hx;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
// 启用hystrix监控
@EnableHystrixDashboard
@EnableHystrix
public class DashboardApp {
    public static void main(String[] args) {
        SpringApplication.run(DashboardApp.class,args);
    }
}

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/7321.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

信息收集与运用

目录 一.实验目的 二.实验原理 三.实验内容 一.收集信息 二.猜解密码 三.密码强度检测 源码 测试用例 程序输出结果​编辑 ​四.小结与讨论 1.举出保护个人敏感信息的方法&#xff08;最少三点&#xff09;。 2.如何提高你的密码强壮性&#xff0c;以避免黑客利用密…

Java类加载过程面试总结

什么是Java的类加载机制 Java 虚拟机一般使用 Java 类的流程为&#xff1a;首先将开发者编写的 Java 源代码&#xff08;.java文件&#xff09;编译成 Java 字节码&#xff08;.class文件&#xff09;&#xff0c;然后类加载器会读取这个 .class 文件&#xff0c;并转换成 jav…

05.List的介绍

1. List 在集合框架中&#xff0c;List是一个接口&#xff0c;继承自Collection。 Collection也是一个接口&#xff0c;该接口中规范了后序容器中常用的一些方法&#xff0c;具体如下所示&#xff1a; Iterable也是一个接口&#xff0c;表示实现该接口的类是可以逐个元素进行遍…

仿真与测试:单元测试与Test Harness

本文描述单元测试的概念&#xff0c;以及Test Harness建立的方法和简单的单元测试过程。 文章目录1 单元测试1.1 场景举例1.2 简单的测试方法2 Test Harness建立2.1 模型配置2.2 创建Test Harness3 总结1 单元测试 单元测试&#xff0c;简单来说就是在Simulink模型中只测试一小…

63-哈希表

目录 1.哈希表的概念 2.哈希函数的概念 3.哈希函数的设计 3.1.key为整型时哈希函数的设计 3.1.1.普通整数 3.1.2.负整数 3.1.3.大整数 PS&#xff1a;哈希函数设计的3个要求&#xff1a; PS&#xff1a;2种类型的哈希函数&#xff08;大整数&#xff09; 3.2.key为其…

【数据结构】树与二叉树的基本概念及性质

目录 一、树的基本概念 1️⃣树的定义 2️⃣基本术语 3️⃣树的性质 二、二叉树的概念 1️⃣二叉树的定义 2️⃣特殊二叉树 3️⃣二叉树的性质 参考资料 一、树的基本概念 1️⃣树的定义 数据结构中的树是什么❓ 树是 个结点的有限集。有且仅有一个特定的称为根(上图A结点…

C++ [内存管理]

本文已收录至《C语言》专栏&#xff01; 作者&#xff1a;ARMCSKGT 目录 前言 正文 计算机中内存分布 C语言的内存管理 内存申请函数 内存释放函数 C内存管理 new操作符 delete操作符 特性总结 注意 原理探究 operator new和operator delete函数 operator new的底…

【C++】STL之string的使用和模拟实现

初阶的C语法和基本的类和对象我们已经学过了&#xff0c;下面我们会步入一段新的旅程。本章我们将初步了解STL(标准模板库)&#xff0c;并且深入探讨其中一个非常重要的容器———string。 目录 &#xff08;一&#xff09;STL简介&#xff08;了解即可&#xff09; &#xf…

Hashtable、HashMap、ConcurrentHashMap的区别

作者&#xff1a;爱塔居 专栏&#xff1a;JavaEE 作者简介&#xff1a;大三学生&#xff0c;希望和大家一起进步。 Hashtable和HashMap、ConcurrentHashMap 之间的区别? HashMap:线程不安全&#xff0c;key允许为null Hashtable:线程安全&#xff0c;使用synchronized锁Hashta…

2.4 特征工程

2.4 特征工程 李沐 B站:https://space.bilibili.com/1567748478/channel/collectiondetail?sid=28144 课程主页:https://c.d2l.ai/stanford-cs329p/ 1. 为什么需要特征工程: 特征工程 数据集进行特征提取,以使机器学习模型在对经过特征工程处理过的数据进行学习时可以更快…

(02)基础强化:面向对象,变量作用域,封装,继承,虚方法,可访问性

一、面向对象概念复习 1、什么是面向对象&#xff1f;OOP&#xff08;Object-Oriented Programming&#xff09; 一种分析问题的方式&#xff0c;增强了程序的可扩展性。 OOP面向对象编程 OOA面向对象分析 OOAD面向对象分析与设计&#xff08;…

Redis管道(pipeline)

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录前言1、管道(pipeline)的基本概念2、管道实操3、小总结前言 在正式讲解Redis管道之前&#xff0c;先引入一个面试题&#xff1a; 如何优化频繁命令往返造成的性能瓶…

【Hello Linux】线程控制

作者&#xff1a;小萌新 专栏&#xff1a;Linux 作者简介&#xff1a;大二学生 希望能和大家一起进步&#xff01; 本篇博客简介&#xff1a;简单介绍linux中的线程控制 线程控制线程创建线程等待线程终止线程分离线程id和进程地址空间布局线程创建 我们可以通过下面pthread_c…

蓝桥杯基础14:BASIC-1试题 闰年判断

资源限制 内存限制&#xff1a;256.0MB C/C时间限制&#xff1a;1.0s Java时间限制&#xff1a;3.0s Python时间限制&#xff1a;5.0s 问题描述 给定一个年份&#xff0c;判断这一年是不是闰年。 当以下情况之一满足时&#xff0c;这一年是闰年&#xff1a; 1. 年份…

Java面向对象 - 封装、继承和多态的综合练习(答案+知识点总结)第1关:封装、继承和多态进阶(一)+ 第2关:封装、继承和多态进阶(二)

目录 第1关&#xff1a;封装、继承和多态进阶&#xff08;一&#xff09; 报错总结 & 注意事项&#xff1a; 第2关&#xff1a;封装、继承和多态进阶&#xff08;二&#xff09; 源码&#xff1a; 报错总结 & 注意事项&#xff1a; 思维导图免费制作网站&#xf…

软考软件设计师下午试题一

数据流图基本图形元素 外部实体 外部系统是当前系统之外的系统 数据存储 在里面存储数据后还能取出来用 跟实体没有关系&#xff0c;他负责存储加工的数据或者提供数据给加工 加工 灰洞的解释比如输入需要两个才能得到输出的&#xff0c;但是他只输入了一个就是灰洞 数…

Matlab傅里叶级数展开(附结果图)

Matlab傅里叶级数展开&#xff08;附结果图&#xff09; 代码下载链接 代码下载链接 代码下载链接 如下图所示&#xff1a;

“唯一靶点”的华堂宁会成控糖爆品吗?

一上市&#xff0c;两次“断货”的货华堂宁有爆品那味儿了。 2022年10月28日华领医药-B&#xff08;02552.HK&#xff09;公告华堂宁&#xff08;多格列艾汀&#xff09;正式进入商业化&#xff0c;一周后各个渠道便进入到了断货和限售的状态。 对于一个不在传统九大降糖药品…

元宇宙与网络安全

元宇宙是一种虚拟现实空间&#xff0c;用户可以在计算机生成的环境中进行互动。元宇宙的应用范围很广&#xff0c;比如房地产&#xff0c;医疗&#xff0c;教育&#xff0c;军事&#xff0c;游戏等等。它提供了更具沉浸感的体验&#xff0c;更好地现实生活整合&#xff0c;以及…

组件、套件、 中间件、插件

组件、套件、 中间件、插件 组件 位于框架最底层&#xff0c;是由重复的代码提取出来合并而成。组件的本质&#xff0c;是一件产品&#xff0c;独立性很强&#xff0c;组件的核心&#xff0c;是复用&#xff0c;与其它功能又有强依赖关系。 模块 在中台产品和非中台产品中&…
最新文章