SpringCloudAlibaba 学习笔记

news2024/12/25 0:41:35

❤ 作者主页:Java技术一点通的博客
❀ 个人介绍:大家好,我是Java技术一点通!( ̄▽ ̄)~*
🍊 记得关注、点赞、收藏、评论⭐️⭐️⭐️
📣 认真学习,共同进步!!!🎉🎉

第一章 SpringCloud Alibaba入门简介

一、为什么使用Alibaba

  1. 因为:spring netflix进入维护模式
    https://spring.io/blog/2018/12/12/spring-cloud-greenwich-rc1-available-now#spring-cloud-netflix-projects-entering-maintenance-mode

什么是维护模式: spring cloud团队将不会再向模块添加新功能,我们将修复block级别的bug以及安全问题,我们也会考虑并审查社区的小型pull request。我们打算继续支持这些模块,知道Greenwich版本被普遍采用至少一年。

SpringCloud Netflix将不再开发新的组件。

以下spring cloud netflix模块和响应的starter将进入维护模式:

  • spring-cloud-netflix-archaius
  • spring-cloud-netflix-hystrix-contract
  • spring-cloud-netflix-hystrix-dashboard
  • spring-cloud-netflix-hystrix-stream
  • spring-cloud-netflix-hystrix
  • spring-cloud-netflix-ribbon
  • spring-cloud-netflix-turbine-stream
  • spring-cloud-netflix-turbine
  • spring-cloud-netflix-zuul

我们都知道SpringCloud版本迭代是比较快的,因而出现了很多重大ISSUE都还来不及Flix就又推另一个RELEASE了。进入维护模式意思就是目前以及以后一段时间SpingCloud Netflix提供的报务和功能就这么多了,不在开发新的组件和功能了。以后将以雏护和Merge分支Full Request为主。

  1. 所以:spring cloud alibaba来了

官方文档: https://spring.io/projects/spring-cloud-alibaba

主要功能:

  • 服务限流降级:默认支持 WebServlet、WebFlux, OpenFeign、RestTemplate、Spring Cloud Gateway, Zuul, Dubbo 和 RocketMQ 限流降级功能的接入,可以在运行时通过控制台实时修改限流降级规则,还支持查看限流降级 Metrics 监控。
  • 服务注册与发现:适配 Spring Cloud 服务注册与发现标准,默认集成了 Ribbon 的支持。 分布式配置管理:支持分布式系统中的外部化配置,配置更改时自动刷新。
  • 消息驱动能力:基于 Spring Cloud Stream 为微服务应用构建消息驱动能力。
  • 分布式事务:使用 @GlobalTransactional 注解, 高效并且对业务零侵入地解决分布式事务问题。
  • 阿里云对象存储:阿里云提供的海量、安全、低成本、高可靠的云存储服务。支持在任何应用、任何时间、任何地点存储和访问任意类型的数据。
  • 分布式任务调度:提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。同时提供分布式的任务执行模型,如网格任务。网格任务支持海量子任务均匀分配到所有 Worker(schedulerx-client)上执行。
  • 阿里云短信服务:覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

组件:

  • Sentinel:把流量作为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。
  • Nacos:一个更易于构建云原生应用的动态服务发现、配置管理和服务管理平台。
  • RocketMQ:一款开源的分布式消息系统,基于高可用分布式集群技术,提供低延时的、高可靠的消息发布与订阅服务。
  • Dubbo:Apache Dubbo™ 是一款高性能 Java RPC 框架。
    Seata:阿里巴巴开源产品,一个易于使用的高性能微服务分布式事务解决方案。
  • Alibaba Cloud OSS: 阿里云对象存储服务(Object Storage Service,简称 OSS),是阿里云提供的海量、安全、低成本、高可靠的云存储服务。您可以在任何应用、任何时间、任何地点存储和访问任意类型的数据。
  • Alibaba Cloud SchedulerX: 阿里中间件团队开发的一款分布式任务调度产品,提供秒级、精准、高可靠、高可用的定时(基于 Cron 表达式)任务调度服务。
  • Alibaba Cloud SMS: 覆盖全球的短信服务,友好、高效、智能的互联化通讯能力,帮助企业迅速搭建客户触达通道。

二、如何使用?

  • Spring官网:https://spring.io/projects/spring-cloud-alibaba

  • GitHub:https://github.com/alibaba/spring-cloud-alibaba

  • GitHub中文文档:https://github.com/alibaba/spring-cloud-alibaba/blob/master/README-zh.md

  • Spring Cloud Alibaba参考文档:https://spring-cloud-alibaba-group.github.io/github-pages/greenwich/spring-cloud-alibaba.html

按照官网一步一步来:
https://spring.io/projects/spring-cloud-alibaba#learn

新建父工程 spring-cloud-alibaba
父工程引入:

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-alibaba-dependencies</artifactId>
            <version>2021.0.1.0</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

三、版本对应

https://github.com/alibaba/spring-cloud-alibaba/wiki/%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E

Spring Cloud Alibaba VersionSentinel VersionNacos VersionRocketMQ VersionDubbo VersionSeata Version
2021.0.1.0*1.8.31.4.24.9.22.7.151.4.2
Spring Cloud Alibaba VersionSpring Cloud VersionSpring Boot Version
2021.0.1.0Spring Cloud 2021.0.12.6.3

第二章 服务注册和配置中心

一、是什么

官方文档:https://nacos.io/zh-cn/docs/what-is-nacos.html

1. nacos(NAming COnfiguration Service):服务注册和配置中心

Nacos = Eureka + Config + Bus
替代Eureka做服务注册中心
替代Config做服务配置中心
  • github地址: https://github.com/alibaba/Nacos
  • Nacos地址: https://nacos.io/zh-cn/

2. Nacos 概念

  • 地域 物理的数据中心,资源创建成功后不能更换。

  • 可用区 同一地域内,电力和网络互相独立的物理区域。同一可用区内,实例的网络延迟较低。

  • 接入点 地域的某个服务的入口域名。

  • 命名空间 用于进行租户粒度的配置隔离。不同的命名空间下,可以存在相同的 Group 或 Data ID 的配置。Namespace 的常用场景之一是不同环境的配置的区分隔离,例如开发测试环境和生产环境的资源(如配置、服务)隔离等。

  • 配置 在系统开发过程中,开发者通常会将一些需要变更的参数、变量等从代码中分离出来独立管理,以独立的配置文件的形式存在。目的是让静态的系统工件或者交付物(如 WAR,JAR 包等)更好地和实际的物理运行环境进行适配。配置管理一般包含在系统部署的过程中,由系统管理员或者运维人员完成。配置变更是调整系统运行时的行为的有效手段。

  • 配置管理 系统配置的编辑、存储、分发、变更管理、历史版本管理、变更审计等所有与配置相关的活动。

  • 配置项 一个具体的可配置的参数与其值域,通常以 param-key=param-value 的形式存在。例如我们常配置系统的日志输出级别(logLevel=INFO|WARN|ERROR) 就是一个配置项。

  • 配置集 一组相关或者不相关的配置项的集合称为配置集。在系统中,一个配置文件通常就是一个配置集,包含了系统各个方面的配置。例如,一个配置集可能包含了数据源、线程池、日志级别等配置项。

  • 配置集 ID Nacos 中的某个配置集的 ID。配置集 ID 是组织划分配置的维度之一。Data ID 通常用于组织划分系统的配置集。一个系统或者应用可以包含多个配置集,每个配置集都可以被一个有意义的名称标识。Data ID 通常采用类 Java 包(如 com.taobao.tc.refund.log.level)的命名规则保证全局唯一性。此命名规则非强制。

  • 配置分组 Nacos 中的一组配置集,是组织配置的维度之一。通过一个有意义的字符串(如 Buy 或 Trade )对配置集进行分组,从而区分 Data ID 相同的配置集。当您在 Nacos 上创建一个配置时,如果未填写配置分组的名称,则配置分组的名称默认采用 DEFAULT_GROUP 。配置分组的常见场景:不同的应用或组件使用了相同的配置类型,如 database_url 配置和 MQ_topic 配置。

  • 配置快照 Nacos 的客户端 SDK 会在本地生成配置的快照。当客户端无法连接到 Nacos Server 时,可以使用配置快照显示系统的整体容灾能力。配置快照类似于 Git 中的本地 commit,也类似于缓存,会在适当的时机更新,但是并没有缓存过期(expiration)的概念。

  • 服务 通过预定义接口网络访问的提供给客户端的软件功能。

  • 服务名 服务提供的标识,通过该标识可以唯一确定其指代的服务。

  • 服务注册中心 存储服务实例和服务负载均衡策略的数据库。

  • 服务发现 在计算机网络上,(通常使用服务名)对服务下的实例的地址和元数据进行探测,并以预先定义的接口提供给客户端进行查询。

  • 元信息 Nacos数据(如配置和服务)描述信息,如服务版本、权重、容灾策略、负载均衡策略、鉴权配置、各种自定义标签 (label),从作用范围来看,分为服务级别的元信息、集群的元信息及实例的元信息。

  • 应用 用于标识服务提供方的服务的属性。

  • 服务分组 不同的服务可以归类到同一分组。

  • 虚拟集群 同一个服务下的所有服务实例组成一个默认集群, 集群可以被进一步按需求划分,划分的单位可以是虚拟集群。

  • 实例 提供一个或多个服务的具有可访问网络地址(IP:Port)的进程。

  • 权重 实例级别的配置。权重为浮点数。权重越大,分配给该实例的流量越大。

  • 健康检查 以指定方式检查服务下挂载的实例 (Instance) 的健康度,从而确认该实例 (Instance) 是否能提供服务。根据检查结果,实例 (Instance) 会被判断为健康或不健康。对服务发起解析请求时,不健康的实例 (Instance) 不会返回给客户端。

  • 健康保护阈值 为了防止因过多实例 (Instance) 不健康导致流量全部流向健康实例 (Instance) ,继而造成流量压力把健康实例 (Instance) 压垮并形成雪崩效应,应将健康保护阈值定义为一个 0 到 1 之间的浮点数。当域名健康实例数 (Instance) 占总服务实例数 (Instance) 的比例小于该值时,无论实例 (Instance) 是否健康,都会将这个实例 (Instance) 返回给客户端。这样做虽然损失了一部分流量,但是保证了集群中剩余健康实例 (Instance) 能正常工作。


3. 架构

在这里插入图片描述

数据模型
Nacos 数据模型 Key 由三元组唯一确定, Namespace默认是空串,公共命名空间(public),分组默认是 DEFAULT_GROUP。

在这里插入图片描述
服务领域模型
在这里插入图片描述
配置领域模型
围绕配置,主要有两个关联的实体,一个是配置变更历史,一个是服务标签(用于打标分类,方便索引),由 ID 关联。
在这里插入图片描述


二、Nacos2.0

  • 新增长连接功能

    Nacos2.0版本相比1.X新增了gRPC的通信方式,因此需要增加2个端口。新增端口是在配置的主端口(server.port)基础上,进行一定偏移量自动生成。
    
  • 新增 鉴权插件

  • 新增 配置加密


三、与其他注册中心对比

服务注册与服务框架CAP模型控制台管理社区活跃度
EurekaAP高可用支持低(2.x版本闭源)
ZookeeperCP一致支持
ConsulCP支持
NacosAP+CP支持

四、切换

nacos可以切换 AP 和 CP ,可使用如下命令切换成CP模式。

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'

五、下载

  • 下载
    地址:https://github.com/alibaba/nacos/releases/download/2.0.4/nacos-server-2.0.4.zip
  • 启动
    进入bin目录,双击startup.cmd进行启动。
  • 端口号8848
  • 可访问 :http://localhost:8848/nacos/index.html 地址,默认账号密码都是nacos
    在这里插入图片描述

六、注册中心功能

1. 服务提供者1

  • 新建模块
    nacos-provider8000

  • pom

    <dependencies>
    
          <!-- spring boot web -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
    
          <!--SpringCloud Alibaba nacos-->
          <dependency>
              <groupId>com.alibaba.cloud</groupId>
              <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
          </dependency>
      </dependencies>
    
  • application.yml

    server:
      port: 8000
    
    
    spring:
      application:
        name: nacos-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
    
  • 创建启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class NacosProvider8000Application {
        public static void main(String[] args) {
            SpringApplication.run(NacosProvider8000Application.class, args);
        }
    }
    
  • controller

    @RestController
    @RequestMapping("/goods")
    public class GoodsController {
    
        @Value("${server.port}")
        Integer port;
    
        @GetMapping("/findById/{id}")
        public String findById(@PathVariable("id")Integer id){
            //业务逻辑
            return "nacos provider.port:"+port+"|id:"+id;
        }
    }
    
  • 启动项目
    在这里插入图片描述


2. 服务提供者2

  • 新建模块
    nacos-provider8001

  • pom

    <dependencies>
    
          <!-- spring boot web -->
          <dependency>
              <groupId>org.springframework.boot</groupId>
              <artifactId>spring-boot-starter-web</artifactId>
          </dependency>
    
          <!--SpringCloud Alibaba nacos-->
          <dependency>
              <groupId>com.alibaba.cloud</groupId>
              <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
          </dependency>
      </dependencies>
    
  • application.yml

    server:
      port: 8001
    
    
    spring:
      application:
        name: nacos-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
    
  • 创建启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class NacosProvider8001Application {
        public static void main(String[] args) {
            SpringApplication.run(NacosProvider8001Application.class, args);
        }
    }
    
  • controller

    @RestController
    @RequestMapping("/goods")
    public class GoodsController {
    
        @Value("${server.port}")
        Integer port;
    
        @GetMapping("/findById/{id}")
        public String findById(@PathVariable("id")Integer id){
            //业务逻辑
            return "nacos provider.port:"+port+"|id:"+id;
        }
    }
    
  • 启动项目
    在这里插入图片描述


3. 服务消费者

  • 新建模块
    nacos-conusmer9000

  • pom

    <dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <!--SpringCloud Alibaba nacos-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-loadbalancer</artifactId>
                <version>3.1.1</version>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
  • application.yml

    server:
      port: 9000
    
    spring:
      application:
        name: nacos-consumer
      cloud:
        loadbalancer:
          ribbon:
            enabled: false
        nacos:
          discovery:
            server-addr: localhost:8848
    
  • 创建启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class NacosConsumer9000Application {
        public static void main(String[] args) {
            SpringApplication.run(NacosConsumer9000Application.class, args);
        }
    }
    
  • 注册RestTemplate

    @Configuration
    public class RestTemplateConfig {
    
        @Bean
        @LoadBalanced //loadbalancer 客户端负载均衡
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    }
    
  • controller

    @RestController
    @RequestMapping("/order")
    public class OrderController {
    
        @Autowired
        private RestTemplate restTemplate;
    
        @GetMapping("/add/{id}")
        public String add(@PathVariable("id")Integer id){
            //业务逻辑
            String url="http://nacos-provider/goods/findById/"+id;
            String result = restTemplate.getForObject(url, String.class);
    
            return result;
        }
    }
    
  • 测试
    在这里插入图片描述

    访问:http://localhost:9000/order/add/1

在这里插入图片描述
在这里插入图片描述


4、整合feign

  • 引入依赖
    <!-- openfeign -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  • 主启动类上添加注解
    @EnableFeignClients
    
  • 新建feign接口
    @FeignClient("nacos-provider")
    public interface GoodsFeign {
    
        @GetMapping("/goods/findById/{id}")
        public String findById(@PathVariable("id")Integer id);
    }
    
  • controller
     @Autowired
        GoodsFeign goodsFeign;
        
        @GetMapping("/add2/{id}")
        public String add2(@PathVariable("id")Integer id){
            //feign
            String str = goodsFeign.findById(id);
    
            return str;
        }
    
  • 测试
    访问:http://localhost:9000/order/add2/1
    在这里插入图片描述
    在这里插入图片描述

七、服务注册中心对比

1. Nacos 生态图

在这里插入图片描述

2. Nacos和CAP

在这里插入图片描述

3. 对比其他注册中心

A:可用性 C:一致性 P:分区容错性

Nacos默认AP。

切换CP:在这里插入图片描述

  • A:可用性
  • C:一致性
  • P:分区容错性

Nacos默认AP。

切换CP:

curl -X PUT '$NACOS_SERVER:8848/nacos/v1/ns/operator/switches?entry=serverMode&value=CP'

八、配置中心功能

1.创建工程

  • 创建新模块
    nacos-client7777
  • 引入依赖
     <dependencies>
            <!-- spring boot web -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
            </dependency>
    
            <!--SpringCloud Alibaba nacos-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-bootstrap</artifactId>
            </dependency>
        </dependencies>
    
  • 添加配置类
    application.yml
    spring:
      profiles:
        active: dev #表示开发环境
    
    bootstrap.yml
    # nacos配置
    server:
      port: 7777
    
    spring:
      application:
        name: nacos-config-client
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 #Nacos服务注册中心地址
          config:
            server-addr: localhost:8848 #Nacos作为配置中心地址
            file-extension: yaml #指定yaml格式的配置
            
    #${spring.application.name}-${spring.profile.active}.${spring.cloud.nacos.config.file-extension}
    
  • 启动类
    @SpringBootApplication
    @EnableDiscoveryClient
    @RefreshScope //开启刷新功能
    public class NacosClient7777Application {
        public static void main(String[] args) {
            SpringApplication.run(NacosClient7777Application.class, args);
        }
    }
    
  • controller
    @RestController
    @RequestMapping("/config")
    @RefreshScope // 开启刷新功能
    public class ConfigClientController {
        @Value("${name}")
        String name;
    
        @GetMapping("/name")
        public String name() {
            return name;
        }
    }
    
    
  • 在Nacos中添加配置信息
    https://nacos.io/zh-cn/docs/quick-start-spring-cloud.html
    在这里插入图片描述
  • 测试
    在这里插入图片描述
  • 更改配置
    在这里插入图片描述
  • 再次访问接口。说明bus的功能也实现了。
    在这里插入图片描述

2. 分类配置在这里插入图片描述

问题1:实际开发中,通常一个系统会准备dev/test/prod环境。如何保证环境启动时服务能正确读取nacos上相应环境的配置文件?

答案:namespace区分。

问题2:一个大型分布式微服务系统有很多微服务子项目,每个微服务项目又都会有相应的开发环境、测试环境、预发环境、正式环境。那怎么对微服务配置进行管理呢?

答案:用group把不同的微服务划分到同一个分组里面去。

Service就是微服务,一个service可以包含多个cluster集群,nacos默认cluster是DEFAULT,Cluster是对指定微服务的一个虚拟划分。

比方说为了容灾,将service微服务分别部署在了北京机房和上海机房,这是就可以给北京机房的service微服务起一个集群名称BJ,给上海的service微服务起一个集群名称SH,还可以尽量让同一个机房的微服务互相调用,以提升效率。

**dgn方案 **

  1. dataid方案(就是nacos的文件名)
    指定spring.profile.active和配置文件的dataID来使不太环境下读取不同的配置 配置空间+配置分组+新建dev和test两个dataid:就是创建-后不同的两个文件名nacos-config-client-dev.yaml、nacos-config-client-test.yaml 通过IDEA里的spring.profile.active属性就能进行多环境下配置文件的读取。

  2. Group方案(默认DEFAULT_GROUP)
    在nacos创建配置文件时,给文件指定分组。 在IDEA中该group内容 实现的功能:当修改开发环境时,只会从同一group中进行切换。

    spring:
      application:
        name: nacos-config-client
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 #Nacos服务注册中心地址
          config:
            server-addr: localhost:8848 #Nacos作为配置中心地址
            file-extension: yaml #指定yaml格式的配置
            group: BJ_GROUP
    

在这里插入图片描述

  1. namespace方案(默认public)
    这个是不允许删除的,可以创建一个新的命名空间,会自动给创建的命名空间一个流水号。 在nacos新建命名空间,自动出现e79f32ec-974a-4e90-9086-3ae5c64db7e3
    在这里插入图片描述
    在IDEA的yml中指定命名空间namespace: e79f32ec-974a-4e90-9086-3ae5c64db7e3
    pring:
      application:
        name: nacos-config-client
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848 #Nacos服务注册中心地址
          config:
            server-addr: localhost:8848 #Nacos作为配置中心地址
            file-extension: yaml #指定yaml格式的配置
            group: BJ_GROUP
            namespace: e79f32ec-974a-4e90-9086-3ae5c64db7e3
    
    在这里插入图片描述

九、集群和持久化配置


第三章 SpringCloud Alibaba Sentinel实现熔断与限流

一、简介

一句话: 就是hystrix的替代!
官网:https://github.com/alibaba/sentinel
中文文档:https://github.com/alibaba/Sentinel/wiki/%E4%BB%8B%E7%BB%8D

随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 以流量为切入点,从流量控制、熔断降级、系统负载保护等多个维度保护服务的稳定性。

Sentinel 具有以下特征:

  • 丰富的应用场景:Sentinel 承接了阿里巴巴近 10 年的双十一大促流量的核心场景,例如秒杀(即突发流量控制在系统容量可以承受的范围)、消息削峰填谷、集群流量控制、实时熔断下游不可用应用等。
  • 完备的实时监控:Sentinel 同时提供实时的监控功能。您可以在控制台中看到接入应用的单台机器秒级数据,甚至 500 台以下规模的集群的汇总运行情况。
  • 广泛的开源生态:Sentinel 提供开箱即用的与其它开源框架/库的整合模块,例如与 Spring Cloud、Apache Dubbo、gRPC、Quarkus 的整合。您只需要引入相应的依赖并进行简单的配置即可快速地接入 Sentinel。同时 Sentinel 提供 Java/Go/C++ 等多语言的原生实现。
  • 完善的 SPI 扩展机制:Sentinel 提供简单易用、完善的 SPI 扩展接口。您可以通过实现扩展接口来快速地定制逻辑。例如定制规则管理、适配动态数据源等。

Sentinel 的主要特性:
在这里插入图片描述
Sentinel 的开源生态:
在这里插入图片描述

Sentinel 分为两个部分:

  • 核心库(Java 客户端)不依赖任何框架/库,能够运行于所有 Java 运行时环境,同时对 Dubbo / Spring Cloud 等框架也有较好的支持。

  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等应用容器。
    在这里插入图片描述


二、下载

下载地址:https://github.com/alibaba/Sentinel/releases
在这里插入图片描述
运行:

java -jar sentinel-dashboard-1.8.6.jar

在这里插入图片描述
http://localhost:8080
在这里插入图片描述
账号和密码都是sentinel
在这里插入图片描述


三、初始化演示工程

  • 新建模块
    cloudalibaba-sentinel-service8000

  • pom

       <!-- SpringCloud ailibaba nacos-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到-->
        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        <!-- SpringCloud ailibaba sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
    
  • yml

    server:
      port: 8000
    
    spring:
      application:
        name: cloudalibaba-sentinal-service
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
            # 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的 端口
            port: 8719
    
  • 主启动类

    @SpringBootApplication
    @EnableDiscoveryClient
    public class CloudalibabaSentinelService8000Application {
    
        public static void main(String[] args) {
            SpringApplication.run(CloudalibabaSentinelService8000Application.class, args);
        }
    
    }
    
  • controller

    @RestController
    public class FlowLimitController {
    
        @GetMapping("/testA")
        public String testA() {
            return "----testA";
        }
    
        @GetMapping("/testB")
        public String testB() {
            return "----testB";
        }
    
    }
    
  • 测试

启动8050,然后刷新sentinel后台页面(因为sentinel采用懒加载策略,所以需要调用服务后才在后台显示) 在浏览器分别输入,然后刷新sentinel后台页面: http://localhost:8000/demo/testA http://localhost:8000/demo/testB
在这里插入图片描述


四、熔断降级

官方文档:
https://github.com/alibaba/Sentinel/wiki/%E7%86%94%E6%96%AD%E9%99%8D%E7%BA%A7

1. 概述

除了流量控制以外,对调用链路中不稳定的资源进行熔断降级也是保障高可用的重要措施之一。一个服务常常会调用别的模块,可能是另外的一个远程服务、数据库,或者第三方 API 等。例如,支付的时候,可能需要远程调用银联提供的 API;查询某个商品的价格,可能需要进行数据库查询。然而,这个被依赖服务的稳定性是不能保证的。如果依赖的服务出现了不稳定的情况,请求的响应时间变长,那么调用服务的方法的响应时间也会变长,线程会产生堆积,最终可能耗尽业务自身的线程池,服务本身也变得不可用。
在这里插入图片描述
现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

注意: 本文档针对 Sentinel 1.8.0 及以上版本。1.8.0 版本对熔断降级特性进行了全新的改进升级,请使用最新版本以更好地利用熔断降级的能力。

2. 熔断策略

Sentinel 提供以下几种熔断策略:

慢调用比例 (SLOW_REQUEST_RATIO):选择以慢调用比例作为阈值,需要设置允许的慢调用 RT(即最大的响应时间),请求的响应时间大于该值则统计为慢调用。当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且慢调用的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求响应时间小于设置的慢调用 RT 则结束熔断,若大于设置的慢调用 RT 则会再次被熔断。

在这里插入图片描述
测试:

  • 代码

     @GetMapping("/testC/{id}")
        public String testC(@PathVariable("id")Integer id){
            if(id==10){
                //复杂的业务逻辑
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
    
            return "itlils testC";
        }
    
  • 设置策略
    在这里插入图片描述

  • 一直访问10
    在这里插入图片描述

  • 过一会儿,访问10
    在这里插入图片描述

异常比例 (ERROR_RATIO):当单位统计时长(statIntervalMs)内请求数目大于设置的最小请求数目,并且异常的比例大于阈值,则接下来的熔断时长内请求会自动被熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。异常比率的阈值范围是 [0.0, 1.0],代表 0% - 100%。
在这里插入图片描述

测试:

  • 代码

    @GetMapping("/testD/{id}")
        public String testD(@PathVariable("id")Integer id){
            if(id==10){
                //异常调用
               int a=1/0;
            }
    
            return "itlils testD";
        }
    
  • 设置策略
    在这里插入图片描述

  • 测试
    在这里插入图片描述

  • 疯狂访问
    在这里插入图片描述

  • 过2秒后
    在这里插入图片描述

异常数 (ERROR_COUNT):当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。在这里插入图片描述
测试:

  • 代码
      @GetMapping("/testE/{id}")
        public String testE(@PathVariable("id")Integer id){
            if(id==10){
                //异常调用
                int a=1/0;
            }
            return "itlils testE";
        }
    
  • 设置策略
    在这里插入图片描述
  • 疯狂测试 http://localhost:8000/demo/testE/10
    在这里插入图片描述
  • 过几秒 测试http://localhost:8000/demo/testE/1
    在这里插入图片描述

五、热点参数限流

官方文档:
https://github.com/alibaba/Sentinel/wiki/%E7%83%AD%E7%82%B9%E5%8F%82%E6%95%B0%E9%99%90%E6%B5%81

1. 是什么?

何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:

  • 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
  • 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
在这里插入图片描述
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点参数限流支持集群模式。


2. 基本使用

  • 引入依赖
     <dependency>
                <groupId>com.alibaba.csp</groupId>
                <artifactId>sentinel-parameter-flow-control</artifactId>
                <version>1.8.4</version>
            </dependency>
    
  • controller
      @GetMapping("/order")
        @SentinelResource(value = "hotKeys")
        public String order(@RequestParam("goodsId")String goodsId,@RequestParam("userId")String userId){
                //业务逻辑
    
            return "用户下单成功";
        }
    
  • 设置规则
    在这里插入图片描述
  • 快速访问http://localhost:8000/demo/order?goodsId=1&userId=10
    在这里插入图片描述
  • 快速访问http://localhost:8000/demo/order?userId=10
    在这里插入图片描述
    说明设置限制源代码第一个参数,成功了。
  • 为了给调用方一个正确的值,改造
    @GetMapping("/order")
        @SentinelResource(value = "hotKeys",blockHandler = "block_order")
        public String order(@RequestParam(value = "goodsId",required = false)String goodsId
                            ,@RequestParam(value = "userId",required = false)String userId){
                //业务逻辑
    
            return "用户下单成功";
        }
    
        public String block_order(@RequestParam(value = "goodsId",required = false)String goodsId
                ,@RequestParam(value = "userId",required = false)String userId,
                 BlockException ex){
            //记录错误日志
            //logger.error(ex.getMessage()))
    
            return "用户下单失败,请稍后重试";
        }
    

在这里插入图片描述

3. 例外情况

秒杀情况下,某个参数goodsId=100,最新手机id,单独设置阈值1000。

  • 配置
    在这里插入图片描述

  • 疯狂访问http://localhost:8000/demo/order?goodsId=100&userId=10 不会降级
    在这里插入图片描述
    注意:参数例外项,仅支持基本类型和字符串类型

    注意:

    加一个:int a=1/0;

  • 业务上的错,sentinel不会管
    在这里插入图片描述

  • 热点key限制,sentinel才会管,疯狂访问
    在这里插入图片描述


六、降级

1. 解释

  • 熔断:微服务自己限流,不可用了。

  • 降级:调用方,提供方错了,返回给客户一个友好对象。

2. 新建3个项目

cloudalibaba-sentinal-provider9001

  • pom

    <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
        </dependency>
        <!-- SpringCloud ailibaba sentinel-->
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
    
  • yml

    server:
      port: 9001
    
    spring:
      application:
        name: cloudalibaba-sentinal-provider
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848
        sentinel:
          transport:
            dashboard: localhost:8080
            # 默认8719端口,假如被占用了会自动从8719端口+1进行扫描,直到找到未被占用的端口
            port: 8719
          web-context-unify: false #关闭收敛URL
    
  • 启动类

    @EnableDiscoveryClient
    
  • controller

    @RestController
    @RequestMapping("/goods")
    public class GoodsController {
        @Value("${server.port}")
        Integer port;
        
        @GetMapping("/findById/{id}")
        public Goods findById(@PathVariable("id") Integer id){
            //servive-->dao/mapper
            Goods goods=new Goods();
            goods.setGoodId(id);
            goods.setPrice(123);
            goods.setTitle("手机.port:"+port);
            goods.setStock(10);
    
            return goods;
        }
    }
    
    
  • domain

    public class Goods implements Serializable {
        private Integer goodId;
        private String title;
        private double price;
        private Integer stock;
    
        public Goods() {
        }
    
    
        public Goods(Integer goodId, String title, double price, Integer stock) {
            this.goodId = goodId;
            this.title = title;
            this.price = price;
            this.stock = stock;
        }
    
        @Override
        public String toString() {
            return "Goods{" +
                    "goodId=" + goodId +
                    ", title='" + title + '\'' +
                    ", price=" + price +
                    ", stock=" + stock +
                    '}';
        }
    
        public Integer getGoodId() {
            return goodId;
        }
    
        public void setGoodId(Integer goodId) {
            this.goodId = goodId;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
    
        public Integer getStock() {
            return stock;
        }
    
        public void setStock(Integer stock) {
            this.stock = stock;
        }
    }
    
    
  • 测试
    在这里插入图片描述


cloudalibaba-sentinal-provider9002

同理。创建。


cloudalibaba-consumer-nacos-consumer8000

  • pom

     <dependencies>
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
                <exclusions>
                    <exclusion>
                        <groupId>org.springframework.cloud</groupId>
                        <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
                    </exclusion>
                </exclusions>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-loadbalancer</artifactId>
                <version>3.1.1</version>
            </dependency>
            <!-- SpringCloud ailibaba sentinel-->
            <dependency>
                <groupId>com.alibaba.cloud</groupId>
                <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-openfeign</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
        </dependencies>
    
  • yml

    server:
      port: 8000
    
    spring:
      application:
        name: cloudalibaba-sentinal-consumer
      cloud:
        nacos:
          discovery:
            server-addr: localhost:8848  #nacos
        sentinel:
          transport:
            dashboard: localhost:8080    #sentinel
            port: 8719
    
    #激活Sentinel对Feign的支持
    feign:
      sentinel:
        enabled: true
    
  • 配置类

    @Configuration
    public class RestConfig {
    
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate(){
            return new RestTemplate();
        }
    }
    
  • controller

    @RestController
    @RequestMapping("/order")
    public class OrderController {
        @Autowired
        RestTemplate restTemplate;
    
        @GetMapping("/add/{id}")
        public Goods add(@PathVariable("id")Integer id){
            String url="http://cloudalibaba-sentinal-provider/goods/findById/"+id;
    
            Goods goods = restTemplate.getForObject(url, Goods.class);
    
            return goods;
    
        }
    
    }
    
  • 实体类

    public class Goods implements Serializable {
        private Integer goodId;
        private String title;
        private double price;
        private Integer stock;
    
        public Goods() {
        }
    
    
        public Goods(Integer goodId, String title, double price, Integer stock) {
            this.goodId = goodId;
            this.title = title;
            this.price = price;
            this.stock = stock;
        }
    
        @Override
        public String toString() {
            return "Goods{" +
                    "goodId=" + goodId +
                    ", title='" + title + '\'' +
                    ", price=" + price +
                    ", stock=" + stock +
                    '}';
        }
    
        public Integer getGoodId() {
            return goodId;
        }
    
        public void setGoodId(Integer goodId) {
            this.goodId = goodId;
        }
    
        public String getTitle() {
            return title;
        }
    
        public void setTitle(String title) {
            this.title = title;
        }
    
        public double getPrice() {
            return price;
        }
    
        public void setPrice(double price) {
            this.price = price;
        }
    
    
        public Integer getStock() {
            return stock;
        }
    
        public void setStock(Integer stock) {
            this.stock = stock;
        }
    }
    
  • 测试
    出现负载均衡
    在这里插入图片描述
    在这里插入图片描述


3. 不同情况下 blockHandler与fallback情况

  • 不配置

      if(id<0){
                throw new IllegalArgumentException("非法参数");
            }else if(id>100){
                throw new NullPointerException("查无此商品");
            }
    
    
  • 只配blockHandler

    public Goods fail_add(@PathVariable("id")Integer id, BlockException ex){
        Goods goods =new Goods();
        goods.setGoodId(-1);
        goods.setPrice(-1);
        goods.setStock(-1);
        goods.setTitle("限流之后的特殊对象");
    
        return go
    

    在这里插入图片描述
    在这里插入图片描述
    正常访问错id
    在这里插入图片描述疯狂访问
    在这里插入图片描述

  • 只配fallback

    @SentinelResource(value = "add",fallback = "fallback_add")
    
    //业务上的错的话
    public Goods fallback_add(@PathVariable("id")Integer id, Throwable ex){
        Goods goods =new Goods();
        goods.setGoodId(-2);
        goods.setPrice(-2);
        goods.setStock(-2);
        goods.setTitle("业务出错之后的特殊对象");
    
        return goods;
    }
    

在这里插入图片描述

  • 都配置
    @SentinelResource(value = "add",blockHandler = "fail_add",fallback = "fallback_add")
    

在这里插入图片描述
-1 慢慢访问

image-20220429181559790

-1 疯狂访问
在这里插入图片描述

  • 忽略某些异常
     @SentinelResource(value = "add",blockHandler = "fail_add",fallback = "fallback_add",
                exceptionsToIgnore = {IllegalArgumentException.class})
    

在这里插入图片描述
在这里插入图片描述
**

七、feign调用

  • pom

    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
    </dependency>
    
  • yml

    #前面也已经添加了
    #激活Sentinel对Feign的支持
    feign:
      sentinel:
        enabled: true
    
  • 主启动类

    @EnableFeignClients
    
  • feign接口

    @FeignClient(value = "cloudalibaba-sentinal-provider",fallback = GoodsFeignImpl.class)
    public interface GoodsFeign {
        @GetMapping("/goods/findById/{id}")
        public Goods findById(@PathVariable("id") Integer id);
    }
    
  • 实现类PaymentFallbackService

    @Component
    public class GoodsFeignImpl implements GoodsFeign{
        @Override
        public Goods findById(Integer id) {
            Goods goods =new Goods();
            goods.setGoodId(-3);
            goods.setPrice(-3);
            goods.setStock(-3);
            goods.setTitle("feign出错之后的特殊对象");
    
            return goods;
        }
    }
    
  • controller

    @Autowired
    GoodsFeign goodsFeign;
    
    @GetMapping("/add1/{id}")
    public Goods add1(@PathVariable("id")Integer id){
        Goods goods = goodsFeign.findById(id);
        return goods;
    }
    
  • 测试出错,直接停了provider
    在这里插入图片描述


八、配置持久化

sentinel的流控配置是临时的,所以我们可以把配置持久化到nacos。

  • pom
    <!-- SpringCloud ailibaba sentinel-datasource-nacos 持久化需要用到-->
    <dependency>
        <groupId>com.alibaba.csp</groupId>
        <artifactId>sentinel-datasource-nacos</artifactId>
    </dependency>
    
  • yml
       sentinel: 
    	      datasource:
    	        ds1:
    	          nacos:
    	            server-addr: localhost:8848  #nacos
            		dataId: ${spring.application.name}
    	            groupId: DEFAULT_GROUP
    	            data-type: json
    	            rule-type: flow
    
  • nacos添加配置
    [
        {
            "resource": "/order/add1/{id}",
            "limitApp": "default",
            "grade": 1,
            "count": 1,
            "strategy": 0,
            "controlBehavior": 0,
            "clusterMode": false
        }
    ]
    
  • resource:资源名称;
  • limitApp:来源应用;
  • grade:阈值类型,0表示线程数,1表示QPS;
  • count:单机阈值;
  • strategy:流控模式,0表示直接,1表示关联,2表示链路;
  • controlBehavior:流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
  • clusterMode:是否集群
    在这里插入图片描述
  • 测试
    在这里插入图片描述

创作不易,如果有帮助到你,请给文章点个赞和收藏,让更多的人看到!!!
关注博主不迷路,内容持续更新中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

疫情卷土重来,如何利用SRM系统打造数字化的“免疫系统”

2022年末&#xff0c;国内疫情再次卷土重来&#xff0c;形势严峻。国内企业也再次面临业务发展的压力。但实际上&#xff0c;在疫情常态化后&#xff0c;我国许多大中型企业都建立了全面的数字化“免疫系统”&#xff0c;增强了抗风险和跨周期的能力&#xff0c;大大增强了抵御…

【B站】Presto + Alluxio:B站数据库系统性能提升实践

欢迎来到【微直播间】&#xff0c;2min纵览大咖观点 在日常线上生产环境中有大量的数据需要被访问&#xff0c;为了保证数据同步以及查询效率&#xff0c;需要耗费较大的资源&#xff0c;同时&#xff0c;很多被查询和访问的数据是重复的&#xff0c;这对数据库系统造成极大压…

C++类和对象概念及实现详解(下篇)

文章目录 一、类的六个默认成员函数详解 1、拷贝构造 1、1 拷贝构造的引入及概念 1、2 拷贝构造函数的特征 2、赋值运算符重载 2、1 运算符重载 2、2 赋值运算符重载 3、普通对象取地址 4、const对象取地址 二、类和对象重点知识点 1、初始化列表 2、static成员 3、友元函数 4、…

一文带你走进MySQL索引

文章目录索引1. 索引的介绍2. 索引的本质3. 索引的结构3.1 Hash3.2 B树3.3 常见面试题之为什么用B树4. 索引的分类4.1 功能逻辑层次4.2 存储形式层次5. 索引的失效5.1 最左前缀原则5.2 索引失效的场景6. 索引常见面试题7. 总结及参考文献索引 1. 索引的介绍 索引是通过某种算…

潘多拉-视频播放器,一个轻量的视频播放器

潘多拉-视频播放器 轻量视频播放器,该项目是从https://github.com/getActivity/AndroidProject-Kotlin 中抽离出的一个视频播放器,之前没有 单独设置项目,我在使用过程中觉得这个挺方便好用的,所以为了方便使用,单独剥离出来,可以单独在项目中使用,后续我也会基于这个项目进行…

【数据结构】Leetcode旋转数组

目录 一、题目说明 二、题目解析 一、题目说明 题目链接&#xff1a;leetcode旋转数组 给你一个数组&#xff0c;将数组中的元素向右轮转k个位置&#xff0c;其中k是非负数。 示例1&#xff1a; 输入&#xff1a;nums [1,2,3,4,5,6,7],k 3 输出&#xff1a;[5,6,7,1,2,3,4…

给大家分享5款轻便小巧的好软件

随着网络信息技术的发展&#xff0c;越来越多的人在办公时需要用到电脑了。如果你想提高办公效率&#xff0c;那么就少不了工具的帮忙&#xff0c;今天给大家分享5款办公必备的好软件。 1.开源分享工具——ShareX ShareX 是一款 Windows 上开源的截图、文件共享和生产力工具&…

IB 生申请德国大学的条件

Hallo! 你是IB生吗&#xff1f;是否有去德国读大学的意愿&#xff1f;来看看IB生申请德国大学的条件吧~ 01IB课程简介 IB课程包括六个学科组&#xff0c;其中一个必须从 IBO 指定的第 1 到第 5 个科目组中选修&#xff0c;另外还有一个可选科目&#xff0c;可以从六个科目组中选…

华为智能基座【计算机组成原理】

华为智能基座【计算机组成原理】前言推荐华为智能基座实验1 基于QEMU的鲲鹏开发环境搭建1.1 QEMU的安装配置1.1.1 QEMU下载安装1.1.2 环境变量配置1.2 openEuler操作系统安装1.2.1 环境准备1.2.2 openEuler虚拟机创建1. 打开虚拟机2. 修改串口并登录1.3 网络配置1.3.1 参数设置…

骨传导耳机到底好不好用,五款好用的骨传导蓝牙耳机分享

很多人刚接触骨传导耳机&#xff0c;都会有一个疑问&#xff0c;骨传导耳机到底好不好用&#xff0c;下面我就为大家解答疑惑&#xff0c;骨传导耳机开放式的佩戴方式&#xff0c;更加舒适&#xff0c;使用更加安全&#xff0c;在平常使用都是很好用的&#xff0c;还不知道选择…

JAVA生成二维码QRcode

JAVA生成二维码QRcode1 : 配置集成1.1、配置maven1.2、配置文件1.3、logo文件2 : 代码集成2.1、加载配置文件2.2、工具类2.3、测试类3 : 测试结果3.1、生成二维码3.2、扫描结果3.3、资源1 : 配置集成 1.1、配置maven pom文件中添加一下配置 <!-- QR code --> <depe…

立根铸魂 崛起数智时代 欧拉部署超300万套

操作系统产业峰会2022于12月28日在线上举办。本次峰会由开放原子开源基金会、中国软件行业协会、CCF&#xff08;中国计算机学会&#xff09;开源专委会、绿色计算产业联盟、中关村科学城管委会共同主办&#xff0c;以“立根铸魂 崛起数智时代”为主题&#xff0c;汇聚全产业链…

Day842.Future -Java 并发编程实战

Future Hi&#xff0c;我是阿昌&#xff0c;今天学习记录的是关于Future的内容。 ThreadPoolExecutor 的 void execute(Runnable command) 方法&#xff0c;利用这个方法虽然可以提交任务&#xff0c;但是却没有办法获取任务的执行结果&#xff08;execute() 方法没有返回值&…

Java Web高级面试题(二)

✅作者简介&#xff1a;热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏&#xff1a;Java面试题…

总体分布、样本分布、抽样分布的区别

总体分布、样本分布、抽样分布的区别 参考自&#xff1a;THREE DISTRIBUTIONS 1.总体分布 The population is the whole set of values, or individuals, you are interested in. The population which consists of a set of scores (5, 6, 7, 8) which distribute around a …

比Hive还快10倍的大数据计算引擎

最近几年&#xff0c;Presto这个大数据组件越来越多地出现在程序员的岗位需求中&#xff0c;很多应届同学一番自我检查后发现&#xff0c;在学校都没怎么接触过&#xff0c;更不用说了解了。 某游戏公司岗位需求 Presto到底是个啥&#xff1f; 有什么用&#xff1f; 适合哪些…

月薪9K!前台测试男生偷偷努力,工资翻倍转行5G网络优化工程师,“卷死”所有人!

你是否有过这样的生活&#xff1f; 每天重复着外场测试&#xff0c;抱着电脑&#xff0c;手机在户外验证基站信号;长期的出差&#xff0c;频繁的更换城市;每个月领着3500块钱的工资&#xff0c;可能再工作2-3年会涨到4000元&#xff0c;技术也不可能有任何的突破。生活重复单调…

Ubuntu 上安装conan + Cmake

目录 1. 在用户目录下创建共享目录&#xff0c;然后将共享目录挂载到上去 2. 安装新版本的cmake 3. 安装conan 4. 配置CONAN环境 5. 配置conan的访问服务器URL 6. Linux 平台需要切换gcc编译器版本为c11以及version 7. 安装opengl开发库 1. 在用户目录下创建共享目录&…

springboot+mybatis如何快速插入大量数据

在公司业务开发过程中&#xff0c;我们经常会遇到往数据库表中插入大量数据的场景&#xff0c;比如excel批量导入数据。那么该如何快速地插入数据呢&#xff1f;我们可以考虑使用批量插入来实现&#xff0c;该方案实测每秒能达到35000条&#xff0c;后附具体实现代码。接下来我…

经典蓝牙连接过程

ACL是连接基础&#xff0c;sco需要再ACL连接成功后建立连接。基本链接流程如下: 一、创建连接 从用户点击扫描到的蓝牙设备开始&#xff0c;发起连接的设备会发送create_connection给controller。controller会进行page过程。 而后会底层链接完成&#xff0c;这个完成仅仅是确认…