Spring Cloud Alibaba微服务组件学习笔记

news2024/11/13 12:35:05

文章目录

  • 一、版本说明
    • 版本关系
    • 项目创建
  • 二、Nacos注册中心
    • 什么是Nacos
    • Nacos注册中心
    • 核心功能
    • Nacos Server部署(windows版本)
    • Nacos Client服务
    • Nacos Server配置项详解:
    • Nacos集群搭建:
  • 三、Ribbon负载均衡
    • 主流的负载方案:
    • 常见的负载均衡算法,实现接口 `IRule`:
    • Nacos使用Ribobn
    • 自定义负载算法:
    • 自定义配置文件修改负载策略:
    • Ribbon饥饿加载:
    • Load Balancer替换Ribbon
  • 四、微服务调用组件Feign
    • 使用OpenFeign
    • Feign的自定义配置
      • 日志配置
      • 契约配置
      • 超时时间配置
      • 自定义拦截器实现认证
  • 五、Nacos配置中心
    • 新增Nacos Config配置文件
    • 搭建Nacos Config的服务读取配置文件
  • 六、Sentinel分布式高可用组件
    • 快速开始:
    • @SentinelResource的使用
    • 流量控制规则 ==*FlowRule*==,服务提供端使用
    • 熔断降级规则 ==*DegradeRule*==,服务消费端使用
    • Sentinel控制台
    • Spring Cloud Alibaba整合Sentinel:
  • 七、分布式事务Seata


一、版本说明

  1. 版本关系

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

    在这里插入图片描述

    在这里插入图片描述

    链接包含了项目所需依赖,只需在 <dependencyManagement> 中添加 Spring Cloud Alibaba 依赖即可:

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

    父项目添加依赖后,子项目自动继承依赖。

  2. 项目创建

    • 阿里云脚手架:https://start.aliyun.com/
    • Spring脚手架:https://start.spring.io/

二、Nacos注册中心

  1. 什么是Nacos

    集:注册中心配置中心服务管理 的平台。

    关键特性:

    • 服务发现和服务健康监测
    • 动态配置服务
    • 动态 DNS 服务
    • 服务及其元数据 (服务名称、地址、命名空间等) 管理
  2. Nacos注册中心

    引入心跳机制,定时接收心跳信息,若没有按时接收到心跳 (默认5秒发送一次) ,则注册中心便会将status改为down;若15秒内还没有心跳,则不会再拉取该服务,同时服务健康状态变为false;再后达到一定时间 (默认30秒) 没有心跳,则直接剔除该服务。
    在这里插入图片描述

  3. 核心功能

    Nacos Discovery

    • 服务注册:Nacos Client发送REST请求向Nacos Server注册服务;
    • 服务心跳:注册后,会维护一个定时心跳,默认5秒一次;
    • 服务同步:Nacos Server集群之间会互相同步服务实例;
    • 服务发现:Nacos Client在调用服务时,会缓存Server中的服务清单到本地,并启动一个定时任务定时拉取最新服务清单来更新本地缓存;
    • 服务监控检查:Nacos Server会开启一个定时任务检查注册服务的健康状态,15s未接收到心跳,健康状态将视为false,服务发现不会拉取;30s没有心跳,则直接剔除该服务实例。
  4. Nacos Server部署(windows版本)

    Nacos服务端下载 :https://github.com/alibaba/nacos/releases/;自行选择合适的版本下载,源码等。

    Nacos帮助文档 :https://nacos.io/zh-cn/docs/what-is-nacos.html/

    • 配置启动方式为单机模式 (默认为集群方式):
      • 编辑 nacos/bin/startup.cmd 文件,将 set MODE="cluster" 修改为 set MODE="standalone" 模式;
      • 配置Nacos服务,nacos/conf/application.properties 修改端口号、超时时间、最大连接数、数据源 等信息,默认存储位置是内存中,集群启动一般设置为MYSQL中;
      • 登录账户密码默认都是nacos;
    • 注意:Nacos2.0.3版本对 JDK 的要求,如果启动失败,先更新 JDK 版本!此处使用的是1.8.0_311
  5. Nacos Client服务

    1. 引入Nacos服务发现的依赖,版本由父工程提供:

      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
      </dependency>
      
    2. yml配置:

      # 应用服务 WEB 访问端口
      server:
        port: 8080
      # 应用名称
      spring:
        application:
          name: order-service   # 注册 Nacos Server将采用应用名称
        cloud:
          nacos:
            server-addr: 127.0.0.1:8848 # 注册地址
            discovery:
              username: nacos   # Nacos Server登录账户、密码、命名空间(自定义 dev / product)
              password: nacos
              namespace: public
              ephemeral: false	# 默认true,切换临时/永久,永久实例宕机后注册中心不会删除服务
      
    3. 如果使用 RestTemplate 模板类调用接口,需要配置如下:

      @Configuration
      public class RestTemplateConfig {
          @Bean
          @LoadBalanced		//此处一定要配置负载均衡注解,Nacos不知道调用哪个服务
          public RestTemplate getRestTemplate(RestTemplateBuilder builder) {
              RestTemplate restTemplate = builder.build();
              return restTemplate;
          }
      }
      
    4. 启动类注解:@EnableDiscoveryClient,可加可不加,高版本的SpringCloud做了处理;

    5. 代码参考

      • order-service代码,服务调用者:
      @RestController
      @RequestMapping("/order")
      public class OrderController {
      
          @Autowired
          private RestTemplate restTemplate;
      
          @RequestMapping("/getOrder")
          public String getOrder(){
              String info =
                      restTemplate.getForObject("http://stock-service/stock/getStock", String.class);
              return "HELLO WORLD!" + info;
          }
      }
      
      • stock-service代码,服务提供者,此处复制启动类端口8082测试负载均衡,默认轮询:
      @RestController
      @RequestMapping("/stock")
      public class StockController {
      
          @Value("${server.port}")
          private String port;
      
          @RequestMapping("/getStock")
          public String getStock(){
              return "下单了!" + port;
          }
      }
      
  6. Nacos Server配置项详解:

    • 命名空间:namespace,可创建多个命名空间,区分不同的项目或项目组等;

      在这里插入图片描述

    • 服务管理

      在这里插入图片描述

      (1) 服务列表:

      • 保护阈值:取值范围0~1,0表示不开启;当 健康实例 / 总实例数 < 阈值 时,服务会将不健康的服务拿去使用,防止雪崩;

      • 临时实例:ephemeral,默认true,切换临时/永久,永久实例宕机后注册中心不会删除服务,结合保护阈值使用;

      • 权重:weight,结合负载均衡策略使用,越大则调用的次数越多;

      • 分组:group,默认值“DEFAULT_GROUP”,比命名空间更细致的划分;

      • 元数据:metadata,键值对类型的值,用于扩展功能;

        在这里插入图片描述

      (2) 订阅者列表:

      ​ 用于查询哪个服务被调用,调用者名称等信息;

    • 权限管理:配置登录Nacos的账户、密码、访问权限等信息;

    • 配置管理:统一配置服务的配置项,类似Spring Cloud Config的功能;

    • 集群管理:Nacos集群的配置;

  7. Nacos集群搭建:

    环境:JDK1.8+,Maven3.3+,Nginx,MYSQL5.7+;

    参考文档:https://nacos.io/zh-cn/docs/cluster-mode-quick-start.html

    1. 复制三个节点,分别安装Nacos,搭建伪集群测试;

    2. 修改配置文件 application.propprties,配置数据源,MYSQL5.7+;

    3. 修改配置文件cluster.conf.example,改为cluster.conf,内部配置集群的 IP 地址:

      # ip:port
      192.168.2.100:8849
      192.168.2.101:8850
      192.168.2.102:8851 
      
    4. 数据库运行Nacos的sql脚本,创建数据库;

    5. 修改启动脚本 startup.sh:

    • 启动方式为集群:set MODE="cluster"
    • 内存不足时 (此处虚拟机内存较小) ,修改小一些: JAVA_OPT="${JAVA_OPT} -server -Xms512m -Xmx512m -Xmn256m -XX:MetaspaceSize=64m -XX:MaxMetaspaceSize=128m"
    1. 官方推荐,nginx作为反向代理:

      • 配置 nginx.conf 配置文件:

        upstream nacoscluster { 
            server 192.168.2.100:8849;
            server 192.168.2.101:8850;
            server 192.168.2.102:8851;
        }	
        server { 
            listen 8848;
            server_name localhost;
            location /nacos/ {
            	# 反向代理的路径,如访问http://192.168.2.100:8848将均衡代理到对应的Nacos上
            	proxy_pass http://nacoscluster/naocs/;
            }
        }
        

三、Ribbon负载均衡

Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡工具,它通过Load Balance获取到服务端的所有机器实例,基于某种规则去调用这些服务,同时也可以实现我们自己的负载均衡算法。

  1. 主流的负载方案:

    • 集中式负载均衡 (服务端),硬件 / 软件的方式,如Nginx;
    • 客户端负载均衡,根据自身请求的状况做负载均衡;
  2. 常见的负载均衡算法,实现接口 IRule

    在这里插入图片描述

    • 随机

    • 轮询

    • 加权轮询

    • 地址Hash算法

    • 最小连接数

      ……

  3. Nacos使用Ribobn

    1. 依赖问题;nacos-discovery 中添加了Ribbon的依赖,所以无需在添加!
    2. 添加注解:@LoadBalanced 加在RestTemplate配置类中;
    3. RestTemplate调用的 url 地址,将 IP 改为对应的服务名称;
  4. 自定义负载算法:

    1. 自定义配置类,可自己实现AbstractLoadBalancerRule抽象类,重写choose方法,使用getLoadBalancer方法获取所有的服务,按需返回指定的服务,即可实现自己需要的负载策略:

      @Bean
      public IRule getIRule() {
          return new NacosRule();
      }
      

      注意此处的配置类不能放在启动类可扫描到的包下,否则会被所有服务共享策略!!!

    2. 启动类配置注解,针对某一服务进行负载均衡策略:

      @SpringBootApplication
      @RibbonClients(value = {
          @RibbonClient(name = "order-service", configuration = RestTemplateConfig.class),
          @RibbonClient(name = "stock-service", configuration = RestTemplateConfig.class)
      })
      public class OrderNacosApplication {
      
          public static void main(String[] args) {
              SpringApplication.run(OrderNacosApplication.class, args);
          }
      
      }
      
  5. 自定义配置文件修改负载策略:

    采用NacosRule,它实现了Nacos的权重,可以在Nacos中配置,也可以在配置文件中配置weight,设置为0表示不使用此服务。

    # 基于配置文件形式的 针对单个服务的 Ribbon 负载均衡策略
    stock-service:  # 被调用者的服务名称
      ribbon:
        NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
    
  6. Ribbon饥饿加载:

    默认关闭,开启后,服务将在启动时初始化负载策略,解决服务初次访问速度响应慢的问题;

    ribbon:
      eager-load:
        enabled: true	# 开启饥饿加载
        # 指定需要饥饿加载的服务名称,多个服务使用逗号分隔
        clients: stock-service, order-service
    
  7. Load Balancer替换Ribbon

    支持RestTemplate、WebClient两种方式;

    1. 添加SpringCloud父依赖:

      <!--父工程添加如下依赖-->
      <dependencyManagement>
          <dependency>
              <groupId>org.springframework.cloud</groupId>
              <artifactId>spring-cloud-dependencies</artifactId>
              <version>${spring-cloud.version}</version>
              <type>pom</type>
              <scope>import</scope>
          </dependency>
      </dependencyManagement>
      
    2. nacos-discovery依赖,排除掉Ribbon,子项目添加Load Balancer依赖:

      <dependency>
          <groupId>com.alibaba.cloud</groupId>
       <artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
          <exclusions>
              <exclusion>
                  <!--排除Ribbon依赖-->
                  <groupId>org.springframework.cloud</groupId>
                  <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
              </exclusion>
          </exclusions>
      </dependency>
      <!--添加loadbalancer依赖-->
      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-loadbalancer</artifactId>
      </dependency>
      
    3. yml文件禁用Ribbon功能:

      spring:
        cloud:
          loadbalancer:
            ribbon:
              enabled: false
      
    4. 启动类配置,类似 @RibbonClients 的用法:

      @LoadBalancerClients(value = {
          @LoadBalancerClient(name = "order-service", configuration = RestTemplateConfig.class),
          @LoadBalancerClient(name = "stock-service", configuration = RestTemplateConfig.class)
      })
      
    5. 自定义负载策略,实现 ReactorLoadBalancer 接口,重写choose方法,实现自己的负载策略。


四、微服务调用组件Feign

Feign 是Netflix开发的声明式、模板化的HTTP客户端。可以更发方便简洁的调用HTTP API。

SpringCloud Openfeign 对Feign 进行了增强,使其支持SpringMVC注解,而且还整合了Ribbon和Nacos。

  1. 使用OpenFeign

    1. 添加父依赖:spring-cloud-dependencies

    2. 添加openfeign依赖:

      <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-openfeign</artifactId>
      </dependency>
      
    3. 服务调用者编写Feign接口,这里需要保证服务提供者服务存在Nacos中:

      /**
       * name:需要调用的服务名称
       * path:也可以去掉,去使用@RequestMapping("/stock")
       */
      @FeignClient(name = "stock-service", path = "/stock")
      public interface StockFeignService {
          @RequestMapping("/getStock")
          String getStock();
      }
      
    4. 启动类开启Feign功能:@EnableFeignClients,添加在启动类或配置类上;

  2. Feign的自定义配置

    1. 日志配置

      • 自定义配置类,配置日志级别:

        @Configuration
        public class FeignConfig {
            @Bean
            public Logger.Level feignLoggerLevel() {
                return Logger.Level.FULL;	// 选择一种配置
             // return Logger.Level.BASIC;
             // return Logger.Level.HEADERS;
             // return Logger.Level.NONE;
            }
        }
        
      • yml配置文件修改Spring默认日志级别,改为只打印Feign的日志:

        # Spring的日志级别是info,而feign的日志级别是debug,不改这里就不会输出feign日志
        logging:
          level:
          	# 只输出指定的Feign接口日志信息
            com.axin.feign.StockFeignService: debug
        
      • 局部日志配置

        • 第一种,将配置类的 @Configuration 去除,而在 @FeignClient 注解上配置属性:

          @FeignClient(name = "stock-service", configuration = FeignConfig.class)
          public interface StockFeignService {
              @RequestMapping("/getStock")
              String getStock();
          }
          
        • 第二种,修改yml配置文件:

          feign:
            client:
              config:
                stock-service:  # 日志的服务名称
                  loggerLevel: BASIC
          
    2. 契约配置

      原生Feign是不支持SpringMVC注解的,所以修改契约配置可以去使用原生的Feign注解,如老项目升级。

      修改配置后,Feign接口将不能使用MVC注解,而是使用原生注解。

      • 配置类修改契约配置:

        @Bean
        public Contract feignContract() {
            return new Contract.Default();
        }
        
      • 配置文件yml修改:

        feign:
          client:
            config:
              stock-service:  # 服务名称
                contract: feign.Contract.Default  # 契约配置,还原原生注解
        
      • 原生注解对应MVC注解:

        @RequestMapping("/getStock") ==> @RequestLine("GET /getStock") 手动配置请求方法;

        @PathVariable ==> @Param

    3. 超时时间配置

      • 全局配置类配置:

        @Bean
        public Request.Options options() {
            return new Request.Options(5000, 10000);
        }
        
      • 配置文件yml配置:

        feign:
          client:
            config:
              stock-service:  # 服务名称
                connectTimeout: 5000    # 连接超时的时间,默认2s
                readTimeout: 10000      # 响应超时的时间,默认5s
        
    4. 自定义拦截器实现认证

      • 配置类配置,自定义拦截器,实现RequestInterceptor接口,重写apply方法,加入Spring容器内;

      • 配置文件yml配置,这里拦截器就无需加入Spring容器了:

        feign:
          client:
            config:
              stock-service:  # 服务名称
                requestInterceptors[0]: # 配置拦截器
                  com.it.config.FeignAuthRequestInterceptor   # 自定义拦截器全路径
        

五、Nacos配置中心

  1. 新增Nacos Config配置文件

    1. Nacos服务端新增配置:

      注:微服务将自动读取Nacos中与微服务名称一样的配置文件名!!!

      在这里插入图片描述

    2. 启用Nacos的权限控制,nacos/conf/application.properties 中修改配置文件:

      权限控制开启后,微服务中必须配置Nacos的用户名和密码,否则报错!!!

      ### If turn on auth system:
      nacos.core.auth.enabled=true	# 默认false
      
  2. 搭建Nacos Config的服务读取配置文件

    1. 添加依赖:

      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
      </dependency>
      
    2. 配置bootstrap.yml文件,此处没有开启权限控制,无需配置Nacos的用户名和密码:

      spring:
        application:
          name: config-service
        cloud:
          nacos:
            server-addr: 127.0.0.1:8848
      
    3. 测试读取配置信息:

      @SpringBootApplication
      public class ConfigNacosApplication {
      
          public static void main(String[] args) {
              ConfigurableApplicationContext applicationContext = 
                  	SpringApplication.run(ConfigNacosApplication.class, args);
              ConfigurableEnvironment environment = 
                  	applicationContext.getEnvironment();
              System.out.println("my.name:" + 
                                 environment.getProperty("my.name"));
              System.out.println("my.password:" + 
                                 environment.getProperty("my.password"));
          }
      
      }
      

      在这里插入图片描述

    4. 测试实时修改Naocs配置中心的配置,微服务将自动拉取新的信息;

    5. 修改微服务配置的文件格式,默认的格式为properties

      spring:
        cloud:
          nacos:
            config:
              file-extension: yaml
      
    6. 配置profiles

      • Nacos配置中心的配置

        dataid的命名:服务名 - 环境 - 文件后缀,如config-nacos-dev.yml;

        注意:默认的配置文件(与服务名相同的dataid的配置文件),则无需添加文件后缀。

      • 本地微服务的配置

        application.yml中,使用 spring.profiles.active 选择 dev / product 环境。

      • 配置文件的优先级

        profiles > 默认 > 自定义dataid配置,优先级大的将覆盖小的,同时配置将互补,配置一项即可。

    7. 配置命名空间namespace,微服务配置后,将读取指定命名空间中的配置信息。

    8. 配置组group,微服务配置后,将读取指定组内的配置信息。

    9. 自定义dataid配置文件的读取:

      共两种方式,二者功能一致,只是优先级不同。

      extension-configs > shared-configs,同时,数组的下标越大优先级越大。

      • shared-configs数组:

        注意:SpringBoot 将优先使用最后读取的配置文件,此处将选择下标1的配置。

        spring:
          cloud:
            nacos:
              server-addr: 127.0.0.1:8848
              config:
                file-extension: yaml
                shared-configs:   # 接收一个数组
                  - data-id: my.config1.yml	# 下标为0
                    refresh: true
                  - data-id: my.config2.yml	# 下标为1,SpringBoot优先使用后读取的配置
                    refresh: true
        
      • extension-configs数组:

        spring:
          cloud:
            nacos:
              server-addr: 127.0.0.1:8848
              config:
                file-extension: yaml
                extension-configs:   # 接收一个数组
                  - data-id: my.config3.yml   # 下标为0
                      refresh: true
                  - data-id: my.config4.yml   # 下标为1
                    refresh: true
        
    10. java类中动态获取配置信息:

      注意:正常情况下,修改配置中心的配置后,类中是无法动态取到的,需要添加注解 @RefreshScope

      @RefreshScope
      @RestController
      @RequestMapping("/config")
      public class ConfigController {
          
          @Value("${my.name}")
          private String name;
          @Value("${my.password}")
          private String password;
          
          @RequestMapping("/show")
          public String show(){
              return this.toString();
          }
      
          @Override
          public String toString() {
              return "ConfigController{" +
                      "name='" + name + '\'' +
                      ", password='" + password + '\'' +
                      '}';
          }
      }
      

六、Sentinel分布式高可用组件

  1. 说明文档:https://github.com/alibaba/Sentinel

Sentinel 是面向分布式服务架构的流量控制组件,主要以流量为切入点,从限流、流量整形、熔断降级、系统负载保护、热点防护等多个维度来保障微服务的稳定性。

Sentinel的特征:

  • 丰富的应用场景:
  • 完备的实时监控:
  • 广泛的开源生态:
  • 完善的SPI扩展点:

Sentinelhystrix对比:

在这里插入图片描述

  1. 快速开始:

    1. 核心依赖:

      <dependency>
          <groupId>com.alibaba.csp</groupId>
          <artifactId>sentinel-core</artifactId>
          <version>1.8.4</version>
      </dependency>
      
    2. 其他依赖:

      <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
      </dependency>
      
    3. 自定义一个Controller:

      import com.alibaba.csp.sentinel.Entry;
      import com.alibaba.csp.sentinel.SphU;
      import com.alibaba.csp.sentinel.slots.block.BlockException;
      import org.springframework.web.bind.annotation.RequestMapping;
      import org.springframework.web.bind.annotation.RestController;
      
      @RestController
      public class HelloWorldController {
      
          @RequestMapping("/hello")
          public String helloWorld() {
              Entry entry = null;
              try {
                  entry = SphU.entry("hello");
                  return "hello world";
              }catch (BlockException be) {
                  return "限流了";
              } catch (Exception e) {
                  e.printStackTrace();
                  return "error";
              } finally {
                  if (entry != null) {
                      entry.exit();
                  }
              }
          }
      
      }
      
    4. 自定义一个Spring的初始化方法,内部添加限流规则:

      import com.alibaba.csp.sentinel.slots.block.RuleConstant;
      import com.alibaba.csp.sentinel.slots.block.flow.FlowRule;
      import com.alibaba.csp.sentinel.slots.block.flow.FlowRuleManager;
      import org.springframework.context.annotation.Configuration;
      
      import javax.annotation.PostConstruct;
      import java.util.ArrayList;
      
      @Configuration
      public class SpringInitConfig {
      
          @PostConstruct  // 初始化方法, 类加载的时候执行, 在这里添加限流规则, 也可在启动类中添加
          private static void initFlowRule() {
              ArrayList<FlowRule> flowRules = new ArrayList<>();
              FlowRule rule = new FlowRule(); // 创建限流规则
              rule.setResource("hello");  //资源名称,可以是类名、方法名、路径名等
              rule.setGrade(RuleConstant.FLOW_GRADE_QPS); //限流等级
              rule.setCount(1);   // 限流阈值, 即每秒钟最多访问1次, 参数类型为double
              flowRules.add(rule);
              // 注册限流规则
              FlowRuleManager.loadRules(flowRules);   // 加载限流规则
          }
      }
      
    5. 端口号配置:

      server:
      	port: 8080
      
    6. 启动项目,浏览器访问:http://localhost:8080/hello

    7. 缺点:代码复杂,嵌入代码过多

  2. @SentinelResource的使用

    1. 文档:https://github.com/alibaba/Sentinel/wiki/%E6%B3%A8%E8%A7%A3%E6%94%AF%E6%8C%81

    2. 添加依赖

      <dependency>
          <groupId>com.alibaba.csp</groupId>
          <artifactId>sentinel-annotation-aspectj</artifactId>
          <version>1.8.4</version>
      
    ```
    1. 配置SentinelResourceAspect切面类,加入到Spring容器中:

      /**
       * 配置SentinelResourceAspect, 会自动拦截@SentinelResource注解的方法
       */
      @Bean
      public SentinelResourceAspect sentinelResourceAspect() {
          return new SentinelResourceAspect();
      }
      
    2. 处理器方法上添加注解==@SentinelResource==:

      @SentinelResource(
              value = "user",
              blockHandler = "userBlockHandler",
              fallback = "userFallback",
              exceptionsToIgnore = {NullPointerException.class}
      )
      @RequestMapping("/user")
      public User getUser(@RequestParam(required = false, value = "num") String num) {
          if (num != null) {
              throw new RuntimeException("降级了");
          } 
          return new User("张三", "23");
      }
      
      public User userBlockHandler(String num, BlockException e) {
          e.printStackTrace();
          return new User("限流了", "0");
      }
      
      public User userFallback(String num, Throwable e) {
          e.printStackTrace();
          return new User("降级了", "0");
      }
      
    3. 在Spring的初始化方法中,内部添加限流规则:

      @PostConstruct  // 初始化方法, 在类加载的时候执行
      private static void initFlowRule() {
          ArrayList<FlowRule> flowRules = new ArrayList<>();
          FlowRule rule2 = new FlowRule(); // 创建限流规则(流量的控制), 可以添加多个
          rule2.setResource("user");  //资源名称,可以是类名、方法名、路径名等,具体参考官方文档
          rule2.setGrade(RuleConstant.FLOW_GRADE_QPS);
          rule2.setCount(1);   // 限流阈值, 即每秒钟最多访问1次, 参数类型为double
          flowRules.add(rule2);
          // 注册限流规则
          FlowRuleManager.loadRules(flowRules);   // 加载限流规则
      }
      
    4. @SentinelResource的常用属性

      • value:资源名称,可以是类名、方法名、路径名等

      • blockHandler:限流时执行的方法,返回值类型与原返回值类型一致,参数可以新增BlockException

      • blockHandlerClass:限流时执行方法存在的类,使用blockHandler指定对应的方法,需要使用static修饰

      • fallback:降级处理器,用于接收异常,当资源被降级时,会调用该处理器,返回值类型与原返回值类型一致,参数可以新增Throwable

      • fallbackClass:降级时执行方法存在的类,使用fallback指定对应的方法,需要使用static修饰

      • exceptionsToIgnore:排除的异常,如果抛出的异常在exceptionsToIgnore中,则不会被限流

      • 注意blockHandlerfallback 同时使用时,blockHandler的优先级更高

      • 注意2:自定义blockHandler 方法时,一定要记得添加对应的异常参数,否则无法生效;

  3. 流量控制规则 FlowRule,服务提供端使用

    @PostConstruct
    private static void initFlowRule() {
        ArrayList<FlowRule> rules = new ArrayList<>();
        FlowRule rule = new FlowRule(); // 创建限流规则
        rule.setResource("hello");  //资源名称
        rule.setGrade(RuleConstant.FLOW_GRADE_QPS); //限流等级,分为:QPS(每秒请求数)、线程数
        rule.setCount(1);   // 限流阈值, 即每秒钟最多访问次数, 参数类型为double
        rules.add(rule);
        // 注册限流规则
        FlowRuleManager.loadRules(rules);   // 加载限流规则
    }
    
  4. 熔断降级规则 DegradeRule,服务消费端使用

    @PostConstruct
    private static void initDegradeRule() {
        ArrayList<DegradeRule> rules = new ArrayList<>();
        DegradeRule rule = new DegradeRule();   // 降级规则
        rule.setResource("degrade");  //资源名称
        /*
         * 60秒内,请求次数超过2次,出现2个异常,则降级,调用降级的方法,降级时间为10秒
         * 降级之后会处于"半开"状态:当10秒之后,若再次调用发生一次异常,则将立即触发降级
         */
        rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);  //降级等级:慢调用比例、异常比例、异常数
        rule.setCount(2);   // 异常数超过2次,则降级
        rule.setMinRequestAmount(2); // 触发熔断的最小请求数,参数类型为int
        rule.setStatIntervalMs(60 * 1000); // 统计时长,单位为毫秒,默认1000ms
        rule.setTimeWindow(10); // 触发熔断时长,单位为秒
        rules.add(rule);
        // 注册降级规则
        DegradeRuleManager.loadRules(rules);    // 加载降级规则
    }
    
  5. Sentinel控制台

    1. 版本:依据 Spring Cloud Alibaba 的版本选择,此处为2.3.7,所以下载1.8.1版本的控制台;

    2. 下载jar包:https://github.com/alibaba/Sentinel/releases

    3. cmd启动:java -jar sentinel-dashboard-1.8.1.jar

    4. 访问:默认端口8080,http://localhost:8080/#/login

    5. 登陆:账户密码都为 sentinel

    6. 启动配置修改:

      • 端口:-Dserver.port=8858

      • 账户:-Dsentinel.dashboard.auth.username=sentinel

      • 密码:-Dsentinel.dashboard.auth.password=123456

      • 日志:

        • -Dlogging.file=.\logs\sentinel-dashboard.log
        • -Dcsp.sentinel.log.dir=.\logs\sentinel-dashboard
      • 自定义批处理文件

        • 新建文本文档,输入如下命令,修改文件名称为:start.bat

          title sentinel-dashboard
          
          java -Dlogging.file=.\logs\sentinel-dashboard.log -Dcsp.sentinel.log.dir=.\logs\sentinel-dashboard -Dserver.port=8858 -Dsentinel.dashboard.auth.username=demo -Dsentinel.dashboard.auth.password=demo -jar sentinel-dashboard-1.8.1.jar
          
          pause
          
        • 访问地址:http://localhost:8858/#/login

    7. Sentinel控制台与微服务建立通信

      1. 引入依赖:

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-transport-simple-http</artifactId>
            <version>1.8.4</version>
        </dependency>
        
      2. 参数配置:

        微服务启动时,配置Sentinel控制台的IP地址及端口号,首次访问接口会注册到控制台内:

        -Dcsp.sentinel.dashboard.server=consoleIp:port

        在这里插入图片描述

        在这里插入图片描述

  6. Spring Cloud Alibaba整合Sentinel:

    1. 添加依赖:

      <dependency>
          <groupId>com.alibaba.cloud</groupId>
          <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
      </dependency>
      
    2. 配置yml参数:

      # 应用名称
      spring:
        application:
          name: sentinel-alibaba
      # sentinel控制台地址
        cloud:
          sentinel:
            transport:
              dashboard: 127.0.0.1:8858
            log:	
           dir: .\logs\sentinel-dashboard	# 设置日志存储位置
      
    3. 用户首次访问路径时,当前服务会自动注册进控制台中;

    4. 自定义限流规则,此时无需再使用@SentinelResource注解一一配置限流方法:

      1. 创建Result类,返回统一的返回值类型;

        public class Result<T> {
            private Integer code;
            private String message;
            private T data;
        
            public Result(Integer code, String message) {
                this.code = code;
                this.message = message;
            }
        
            public static <T> Result<T> error(Integer code, String message) {
                return new Result<T>(code, message);
            }
            // ……省略部分代码
        }
        
      2. 自定义类,实现 BlockExceptionHandler 接口,重写内部方法;

        @Slf4j
        @Component
        public class MyBlockException implements BlockExceptionHandler {
        
            @Override
            public void handle(HttpServletRequest request, HttpServletResponse response, BlockException e) throws Exception {
                log.error("当前的异常资源路径为:" + e.getRule());
                Result<String> result = null;
                if (e instanceof FlowException) {
                    result = Result.error(500, "限流了,请稍后再试");
                } else if (e instanceof DegradeException) {
                    result = Result.error(500, "降级了,请稍后再试");
                } else if (e instanceof ParamFlowException) {
                    result = Result.error(500, "热点参数限流了,请稍后再试");
                } else if (e instanceof SystemBlockException) {
                    result = Result.error(500, "触发系统保护规则了,请稍后再试");
                } else if (e instanceof AuthorityException) {
                    result = Result.error(500, "权限不足,授权规则不通过");
                }
                // 将结果转换为json格式
                response.setStatus(500);
                response.setCharacterEncoding("UTF-8");
                response.setContentType(MediaType.APPLICATION_JSON_VALUE);
                new ObjectMapper().writeValue(response.getWriter(), result);
            }
        }
        
      3. 测试的Controller:

        @RequestMapping("/myBlockExceptionTest")
        public User myBlockExceptionTest() {
            /*
             * 访问每三次,抛出一个异常,否则返回User对象,
             * 测试自定义的限流类
             */
            count++;
            if (count % 3 == 0) {
                throw new RuntimeException("自定义限流异常");
            }
            return new User("自定义的限流类", 23);
        }
        
      4. 在Seninel控制台配置限流规则;

        在这里插入图片描述

      5. 在Seninel控制台配置降级规则;

        在这里插入图片描述

      6. 注意:微服务每次重新启动时需要再次配置规则,后期可自行做Seninel控制台的持久化配置;

    5. 流控模式介绍:

      在这里插入图片描述

      • 直接:直接限制设置的资源路径,可以是路径名,也可以是方法;

      • 关联:当访问设置的资源路径时,对关联的路径进行限制,而不是设置的路径;

        • 新增方法:

          @RequestMapping("/add")		// 使用Jmeter访问此地址
          public User add() {
              return new User("add", 23);
          }
          
          @RequestMapping("/get")		// 使用浏览器访问此地址
          public User get() {
              return new User("get", 23);
          }
          
        • 新增流控规则:

          在这里插入图片描述

        • 使用Jmeter设置一个 线程组 ,增加 取样器HTTP请求 ,增加 监听器 结果树,如图:

          在这里插入图片描述

          在这里插入图片描述

        • 进入浏览器,访问 http://localhost:8123/get ,这时将会显示服务限流;

      • 链路

        对某一方法做限流时,使用链路,可以针对某一个入口方法(具体路径)做限流,在达到设置阈值时,进限流指定的入口方法,而不影响其他;

        • 创建Service及impl,新增流控的方法:

          @Service
          public class SentinelServiceImpl implements SentinelService {
          
              @Override
              @SentinelResource(value = "getUser", blockHandler = "handleException")
              public String getUser() {
                  return "查询成功";
              }
          
              public String handleException(BlockException e) {
                  return "查询失败";
              }
          }
          
        • Controller方法:

          @RequestMapping("/test1")
          public String test1() {
              return sentinelService.getUser() + "test1";
          }
          
          @RequestMapping("/test2")
          public String test2() {
              return sentinelService.getUser() + "test2";
          }
          
        • yml配置文件添加一项配置:

          spring:
            cloud:
              sentinel:
                web-context-unify: false  # 默认为true,将调用链路context收敛,无法使用链路流控,必须修改为false才能使用,
          
        • Sentinel控制台,任选一个getUser方法的簇点链路,配置流控:

          在这里插入图片描述

          在这里插入图片描述

    6. 流控效果介绍:

      在这里插入图片描述

      1. 快速失败:直接完成流控;
      2. Warm Up(激增流量):预热 / 冷启动,使流量在一定时间内,缓慢增加到阈值上限;
        • 冷加载因子:codeFactor,默认是3,即QPS从threshold/3开始,逐渐升至设定的QPS值。
      3. 排队等待(脉冲流量):不会立即流控,而是设置超时时间,让流控的请求在一定时间内去延迟执行,充分利用系统空闲时间;
    7. 熔断降级策略

      1. 慢调用比例:当服务执行时间超过设置的统计时长,称为一次慢调用。超过设定的比例开始降级;
      2. 异常比例:当服务出现的异常次数超过设定的比例开始降级;
      3. 异常数:当服务出现的异常次数超过设定的次数开始降级;
    8. 热点参数流控:针对REST风格,对访问频率高的参数值进行流控降级;

      在这里插入图片描述

      1. 参数索引:参数在方法中所在位置,从零开始计算;
      2. 参数类型:java参数,四类八种;
      3. 参数值:流控的参数具体值,可添加多个;
    9. 系统保护规则

      在这里插入图片描述

      1. LOAD自适应:仅对Linux等系统生效;
      2. 平均RT:当单台机器的入口流量的平均 RT 达到阈值,则自动触发系统保护规则;
      3. 并发线程数:当单台机器的并发线程数达到阈值,则自动触发系统保护规则;
      4. 入口QPS:当单台机器的入口流量的 QPS 达到阈值,则自动触发系统保护规则;
      5. CPU使用率:当CPU使用率超过阈值,则自动触发系统保护规则;
    10. openFeign整合Sentinel

      1. 依赖,nacos,feign,sentinel:

        <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-openfeign</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba.cloud</groupId>
            <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
        </dependency>
        
      2. yml配置文件,开启feign对Sentinel的支持:

        feign:
          sentinel:
            enabled: true
        
      3. 自定义一个异常类,实现feign接口的所在的接口类,并加入Spring容器中;

      4. 在feign的接口类上,声明使用自己的异常类:

        @FeignClient(name = "stock-service", 
                     path = "/stock", 
                     fallback = FeignException.class)
        
    11. Sentinel规则的持久化(此处使用第三种模式:拉模式):

      在这里插入图片描述

      1. 添加三方的依赖:

        <dependency>
            <groupId>com.alibaba.csp</groupId>
            <artifactId>sentinel-datasource-nacos</artifactId>
        </dependency>
        
      2. 在nacos中新增配置如下:

        [
            {
                "resource": "/getUser",	
                "controlBehavior": 0,
                "count": 2,
                "grade": 1,
                "limitApp": "default",
                "strategy": 0,
            }
        ]
        
        • resource:流控的资源路径;
        • count:限流阈值;
        • grade:限流阈值类型,QPS为1,并发线程数为0;
        • limitApp:调用来源,默认default,不区分调用来源;
        • strategy:流控模式,直接、链路、关联;
        • controlBehavior:流控效果, 快速失败、Warm Up、排队等待;
        • clusterMode:是否集群限流
      3. 在application.yml配置文件中新增配置:

        详细配置参考 DataSourcePropertiesConfiguration 配置类

        spring:
          cloud:
            sentinel:
              datasource:   # 源码:DataSourcePropertiesConfiguration配置类
                flow-rule:    # 自定义的名称
                  nacos:    # 可选值:nacos、zk、redis、apollo等等
                    server-addr: localhost:8848   # nacos的ip地址
                    username: nacos   # 用户名
                    password: nacos   # 密码
                    dataId: config-nacos-sentinel-flow-rule   # 配置中心自定义的配置的名称
                    rule-type: flow   # 流控规则,具体查看RuleType枚举类
        

七、分布式事务Seata

  1. Seata官网:https://seata.apache.org/zh-cn/;

  2. 名词解释:

    • TMTransaction Manager,事务管理者。定义全局事务的范围,开始全局事务、提交或回滚;
    • RMResource Manager,资源管理者。管理分支事务处理的资源,与 TC 交谈以注册分支事务和报告分支事务的状态,并驱动分支事务提交或回滚;
    • TCTransaction Coordinator,事务协调者。维护全局和分支事务的状态,驱动全局事务提交或回滚;
  3. 四种事务模式:

    • XA模式:事务提交至事务协调者TC,由TC统一决定是否提交事务;

    • AT模式:事务直接提交,并记录 undo_log 日志(SQL执行前后各一条),异常后根据日志回滚;

    • TCC模式:自行决定事务的提交回滚策略,指定执行的方法;

    • Saga模式:长事务解决方案,一种分布式异步事务。分两种实现:

      • 状态机引擎:通过事件驱动的方法异步执行提高系统吞吐,可以实现服务编排需求;

      • 基于注解和拦截器:开发简单、学习成本低;

    模式一致性隔离性侵入性性能场景
    XA强一致完全隔离对一致性、隔离性有高要求的业务
    AT弱一致依赖全局锁隔离基于关系型数据库的大多数分布式事务场景
    TCC弱一致资源预留隔离prepare
    commit
    cancel
    需编写三个接口
    对性能要求较高的事务。
    有非关系型数据库要参与的事务
    Saga最终一致需编写状态机、
    补偿业务
    业务流程长、业务流程多,
    参与者包含其它公司遗留系统服务,
    无法提供 TCC 模式要求的三个接口
  4. 设计问题处理:

    • 脏写:事务回滚前,需校验数据库与记录日志是否相同,如果不同,说明出现了脏写,需人工处理;
    • 允许空回滚:Try拥堵或其它原因未执行,Cancel执行了;
    • 防悬挂控制:Cancel比Try先执行了,即允许空回滚,但要拒绝空回滚后的Try操作;
    • 幂等控制:Try、Commit、Cancel要保证幂等性,即一次请求和多次请求对系统资源的影响是一致的;
  5. 使用Seata(摘自官网):

    • 基本使用:在需要开启分布式事务的方法上添加注解 @GlobalTransactional 即可;

      @GlobalTransactional
      public void purchase(String userId, String commodityCode, int orderCount) {
          ......
      }
      
    • Seata防止脏写:

      • 方法一:

        @GlobalTransactional
        @Transactional
        public boolean updateA(DTO dto) {
            serviceA.update(dto.getA());
        }
        
      • 方法二:

        @GlobalLock
        @Transactional
        public boolean updateA(DTO dto) {
            serviceA.selectForUpdate(dto.getA());
            serviceA.update(dto.getA());
        }
        

| XA | 强一致 | 完全隔离 | 无 | 差 | 对一致性、隔离性有高要求的业务 |
| AT | 弱一致 | 依赖全局锁隔离 | 无 | 好 | 基于关系型数据库的大多数分布式事务场景 |
| TCC | 弱一致 | 资源预留隔离 | prepare
commit
cancel
需编写三个接口 | 优 | 对性能要求较高的事务。
有非关系型数据库要参与的事务 |
| Saga | 最终一致 | 无 | 需编写状态机、
补偿业务 | 优 | 业务流程长、业务流程多,
参与者包含其它公司遗留系统服务,
无法提供 TCC 模式要求的三个接口 |

  1. 设计问题处理:

    • 脏写:事务回滚前,需校验数据库与记录日志是否相同,如果不同,说明出现了脏写,需人工处理;
    • 允许空回滚:Try拥堵或其它原因未执行,Cancel执行了;
    • 防悬挂控制:Cancel比Try先执行了,即允许空回滚,但要拒绝空回滚后的Try操作;
    • 幂等控制:Try、Commit、Cancel要保证幂等性,即一次请求和多次请求对系统资源的影响是一致的;
  2. 使用Seata(摘自官网):

    • 基本使用:在需要开启分布式事务的方法上添加注解 @GlobalTransactional 即可;

      @GlobalTransactional
      public void purchase(String userId, String commodityCode, int orderCount) {
          ......
      }
      
    • Seata防止脏写:

      • 方法一:

        @GlobalTransactional
        @Transactional
        public boolean updateA(DTO dto) {
            serviceA.update(dto.getA());
        }
        
      • 方法二:

        @GlobalLock
        @Transactional
        public boolean updateA(DTO dto) {
            serviceA.selectForUpdate(dto.getA());
            serviceA.update(dto.getA());
        }
        

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

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

相关文章

网工必备-网络设备配置文件及日志高亮显示Sublime Text

文章目录 下载Sublime Text 4下载高亮配色文件使用方法 之前推荐了一款文本编辑工具【编写脚本及查看日志的高亮文本编辑工具——EverEdit】&#xff0c;可以针对网络工程师们日常的网络设备配置文件及日志的高亮显示&#xff0c;但是需要保存后才可以显示高亮&#xff0c;虽然…

AI预测体彩排3采取888=3策略+和值012路或胆码测试8月14日升级新模型预测第51弹

好长时间没进行总结了&#xff0c;今天咱们做一个总结&#xff0c;总结一下最新模型经过50多期的测试结果&#xff1a; 经过近50多期的测试&#xff0c;当然有很多彩友也一直在观察我每天发的预测结果&#xff0c;得到了一个非常有价值的信息&#xff0c;那就是9码定位的命中率…

深入探讨Linux的进程调度器

Linux操作系统作为一个开源且广泛应用的操作系统&#xff0c;其内核设计包含了许多核心功能&#xff0c;而进程调度器&#xff08;Scheduler&#xff09;就是其中一个至关重要的模块。进程调度器负责决定在任何给定的时刻哪个进程可以运行&#xff0c;以及其运行的顺序。这篇文…

如何编写一个CMakeLists.txt文件(由简到难,较详细)

在Linux系统下&#xff0c;经常使用CMakeLists.txt文件来链接、编译C工程&#xff0c;大部分人clone的代码里都是有CMakeLists.txt文件的&#xff0c;只需要cmake .. 和make就完事了&#xff0c;但在工作中&#xff0c;你必须要有从无到有编写CMakeLists.txt文件的能力。 一、…

一款简易大众点评项目实战——达人探店、关注、附近商圈、签到、UV统计

一款简易大众点评项目实战——达人探店、关注、附近商圈、签到、UV统计 8.达人探店8.1上传接口与发布笔记接口8.2 达人探店-查看探店笔记8.3 达人探店-点赞功能8.4 达人探店-点赞排行榜 9、好友关注9.1 好友关注-关注和取消关注9.2 好友关注-共同关注9.3 好友关注-Feed流实现方…

Visual Studio 2024安装教程(非常详细),从零基础入门到精通,看完这一篇就够了(附安装包)

软件下载 软件&#xff1a;Visual Studio版本&#xff1a;2022语言&#xff1a;简体中文大小&#xff1a;4.11M安装环境&#xff1a;Win11/Win10/Win8/Win7硬件要求&#xff1a;CPU2.0GHz 内存4G(或更高&#xff09;下载通道①百度网盘丨下载链接&#xff1a;https://pan.baid…

C语言-在主函数中输入10个等长的字符串。用另一函数对他们进行排序,然后再主函数输出这10个排好序的数列(分别用数组法和指针法实现)

在主函数中输入10个等长的字符串。用另一函数对他们进行排序&#xff0c;然后再主函数输出这10个排好序的数列&#xff08;分别用数组法和指针法实现&#xff09; 一、数组法实现 void str_sort(char str[][32], int n) {int i, j;for (i 0; i < n - 1; i){for (j 0; j …

Stable Diffusion WebUI安装ControlNet 遇到的问题

最近研究Stable Diffusion &#xff0c;在安装ControlNet遇到了几个问题&#xff0c;总算解决了 1.第一个是连不上github,可以使用国内的这个 https://gitcode.com/gh_mirrors/sd/sd-webui-controlnet.git 2.第二个问题是一直Installing ,虽然下载下来了&#xff0c;但还是…

【Python】函数练习题

1、定义一个函数&#xff0c;用于计算一个字符串中字符a出现的次数并通过return返回。 代码&#xff1a; 2、写函数&#xff0c;判断用户传入的一个值&#xff08;字符串或列表或字典或元组&#xff09;长度是否大于5&#xff0c;如果大于5返回True,反之返回False. 代码&…

Python实现邮件发送时,如何优化邮件内容?

Python实现邮件发送如何设置&#xff1f;使用Python发信技巧&#xff1f; 无论是个人用途还是企业需求&#xff0c;一封优化良好的邮件能够提升用户体验&#xff0c;提高邮件的打开率和响应率。AokSend将探讨在Python实现邮件发送时&#xff0c;如何通过几个关键步骤来优化邮件…

【C#】中IndexOf的用法

在 C# 中&#xff0c;IndexOf 方法是字符串和列表&#xff08;如 List<T>&#xff09;等数据结构中常用的方法&#xff0c;用于查找指定元素或子串首次出现的位置。以下是针对不同情况使用 IndexOf 的示例。 对于字符串 对于字符串类型&#xff0c;IndexOf 方法返回子字…

【Python-办公自动化】1秒比较出2张表格之间的不同并标黄加粗

欢迎来到"花花 Show Python"&#xff0c;一名热爱编程和分享知识的技术博主。在这里&#xff0c;我将与您一同探索Python的奥秘&#xff0c;分享编程技巧、项目实践和学习心得。无论您是编程新手还是资深开发者&#xff0c;都能在这里找到有价值的信息和灵感。 自我介…

本地http://localhost/端口 通过本地服务,远程调用同一网络下的另一台主机的微服务方法

首先需要确保能够ping通另一台主机的ip&#xff0c;切记一定要确保可以ping通&#xff0c;否则无法正常访问 我使用的spring-cloud框架&#xff0c;在spring-cloud框架中进行操作&#xff0c;我是有一个单独的Remote模块用于远程调用&#xff0c;在这里 第一步&#xff1a;需要…

Stable Diffusion绘画 | 提示词中的符号解析

() 小括号-提升权重 每个单词默认的权重值为1&#xff0c; 每套上一层“()”后&#xff0c;权重增加1.1倍&#xff0c;最多可套3层小括号&#xff1a; blue&#xff1a;权重值1 (blue)&#xff1a;权重值1.1 ((blue))&#xff1a;权重值1.21 (((blue)))&#xff1a;权重值1.3…

进程与磁盘管理相关

进程与磁盘管理相关 进程创建&#xff08;或者存在的)的唯一标志》进程控制块 PCB是进程存在的唯一标志&#xff0c;当进程被创建时&#xff0c;操作系统为当前进程创建PCB&#xff0c;当进程结束时&#xff0c;会回收PCB PCB .进程描述信息 。进程控制和管理信息 。资源分…

GPS跟踪环路MATLAB之——数字锁相环

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 GPS跟踪环路MATLAB之——数字锁相环 前言为什么要锁相环科斯塔斯环锁相环的一些基本概念1、捕获、锁定与跟踪的概念2、捕获时间和稳态相差3、相位捕获和频率捕获4、捕获带和同…

《计算机组成原理》(第3版)第5章 输入输出系统 复习笔记

第5章 输入输出系统 一、概述 &#xff08;一&#xff09;输入输出系统的发展概况 1&#xff0e;早期阶段 早期的I/O设备种类较少&#xff0c;I/O设备与主存交换信息都必须通过CPU&#xff0c;如图5-1所示。 图5-1 I/O设备通过CPU与主存交换信息 2&#xff0e;接口模块和DMA…

JavaScript模拟空调效果

JavaScript模拟空调效果https://www.bootstrapmb.com/item/15074 在JavaScript中模拟空调效果主要依赖于前端界面的交互和状态变化&#xff0c;因为实际的温度调节、风扇速度调整等硬件操作无法直接通过JavaScript在浏览器中实现。不过&#xff0c;我们可以通过JavaScript来模…

yaml详解实战,读取实战,以及运行结果解析,以及单引号和双引号对转义符读取的影响

一、 YAML&#xff1a;数据格式 文章&#xff1a;《yaml基本语法&#xff0c;数据类型&#xff0c;对象&#xff0c;数组&#xff0c;复合结构&#xff0c;纯量&#xff0c;引用&#xff1b;文件后缀为.yml或.yaml》 里有一些介绍&#xff0c;以及我自己的理解。 这篇文章偏实战…

nvm介绍、下载、安装、配置及使用

一、背景 在工作中&#xff0c;我们可能同时在进行2个或者多个不同的项目开发&#xff0c;每个项目的需求不同&#xff0c;进而不同项目必须依赖不同版本的NodeJS运行环境&#xff0c;这种情况下&#xff0c;对于维护多个版本的node将会是一件非常麻烦的事情&#xff0c;nvm就…