@SentinelResource和openFeign+sentinel 对远程调用熔断降级加规则持久化的具体实 现

news2024/11/24 7:44:35

@SentinelResource

自定义全局限流处理类

需求分析/图解

  1. 先看前面的一段代码

    这个就是上面的Sentinel 热点规则 注意看我们的限制处理方法在本类中代码的耦合度高 阅读性差 不利于程序的扩展 @SentinelResource的作用就是解决这个需求将处理方法放到一个类中


    @GetMapping("/news")
    @SentinelResource(value = "news", blockHandler = "newsBlockHandler")
    public Result queryNews(@RequestParam(value = "id", required = false) String id,
                            @RequestParam(value = "type", required = false) String type) {
        //在实际开发中, 新闻应该到DB或者缓存获取,这里就模拟
        log.info("到DB 查询新闻");
        return Result.success("返回id=" + id + " 新闻 from DB");
    }

    //热点key限制/限流异常处理方法
    public Result newsBlockHandler(String id, String type,
                                   BlockException blockException) {

        return Result.success("查询id=" + id + " 新闻 触发热点key限流保护 sorry...");
    }

说明: 当配置的资源名news 触发限流机制时,会调用newsBlockHandler 方法

  1. 上面的处理方案存在一些问题
    每个@SentinelResource 对应一个异常处理方法,会造成方法很多异常处理方法和资源请求方法在一起,不利于业务逻辑的分离解决方案-> 自定义全局限流处理类.
  2. 需求: 请编写一个自定义全局限流处理类,完成对异常处理.

代码实现

  1. 修改controller/MemberController.java 增加方法t6()
    /**
     * 解读
     * value = "t6": SentinelResource 资源名
     * blockHandlerClass = CustomGlobalBlockHandler.class: 全局限流处理类
     * blockHandler = "handlerMethod1": 全局限流处理类的哪个方法,可以指定.
     */
    @GetMapping(value = "/t6")
    @SentinelResource(
            value = "t6",
            blockHandlerClass = CustomGlobalBlockHandler.class,
            blockHandler = "handlerMethod1")
    public Result t6() {
        log.info("执行t6() 线程id= " + Thread.currentThread().getId());
        return Result.success("200", "t6()执行成功");
    }
  1. 创建springcloud/handler/CustomGlobalBlockHandler.java

提醒, 创建的异常处理方法需要是static

/**
 * 1. CustomGlobalBlockHandler: 全局限流处理类
 * 2. 在CustomGlobalBlockHandler类中,可以编写限流处理方法,但是要求方法是static
 */
public class CustomGlobalBlockHandler {

    public static Result handlerMethod1(BlockException blockException) {
        return Result.error("400", "客户自定义异常/限流处理方法handlerMethod1() ");
    }
    public static Result handlerMethod2(BlockException blockException) {
        return Result.error("401", "客户自定义异常/限流处理方法handlerMethod2() ");
    }
}

配置实现步骤

  1. 为资源/t6 增加流控规则,方便测试

image.png

image.png
2. 在流控规则菜单,可以看到新增规则

image.png

测试

1 启动Nacos Server 8848

2 启动Sentinel8080 控制台/Sentinel dashboard

3 启动member-service-nacos-provider-10004

4 浏览器: http://localhost:10004/t6

1. 浏览器输入: http://localhost:10004/t6 , 如果QPS 没有超过1, 返回正常结果

image.png

  1. 如果QPS 超过1, 断路器打开,返回自定义限流处理方法信息

image.png

fallback

看一段代码-引出fallback

  1. 修改member-service-nacos-provider-10004 的controller/MemberController.java 增加一段代码.
  2. 就是@SentinelResource的t6方法 我们模拟java异常看看会发生什么
    @GetMapping(value = "/t6")
    @SentinelResource(
            value = "t6",
            blockHandlerClass = CustomGlobalBlockHandler.class,
            blockHandler = "handlerMethod1"
    )
    public Result t6() {
        //假定: 当访问t6 资源次数是5 的倍数时,就出现了一个java 的异常
        if (++num % 5 == 0) {
            throw new RuntimeException("num 的值异常num= " + num);
        }
        log.info("执行t6() 线程id= " + Thread.currentThread().getId());
        return Result.success("200", "t6()执行成功");
    }
  1. 浏览器: http://localhost:10004/t6 , 看效果当num 为5 的整数时,返回的是error 页面,不友好.

image.png

  1. 怎么解决=> 使用fallback

基本介绍

1 blockHandler 只负责sentine 控制台配置违规

2 fallback 负责Java 异常/业务异常

需求分析/图解

  1. 需求: 请编写一个自定义全局fallback 处理类, 处理java 异常/业务异常
  2. 也就是解决前面我们提出的问题

代码实现

1.在member-service-nacos-provider-10004 创建/handler/CustomGlobalFallbackHandler.java

/**
 * CustomGlobalFallbackHandler: 全局fallback处理类
 * 在CustomGlobalFallbackHandler类中,可以去编写处理java异常/业务异常方法-static
 */

public class CustomGlobalFallbackHandler {

    public static Result fallbackHandlerMethod1(Throwable e) {
        return Result.error("402","java异常 信息=" + e.getMessage());
    }

    public static Result fallbackHandlerMethod2(Throwable e) {
        return Result.error("403","java异常 信息=" + e.getMessage());
    }
}

  1. 在member-service-nacos-provider-10004 修改controller/MemberController.java
    /**
     * value = "t6" 表示 sentinel限流资源的名字
     * blockHandlerClass = CustomGlobalBlockHandler.class : 全局限流处理类
     * blockHandler = "handlerMethod1": 指定使用全局限流处理类哪个方法,来处理限流信息
     * fallbackClass = CustomGlobalFallbackHandler.class: 全局fallback处理类
     * fallback = "fallbackHandlerMethod1": 指定使用全局fallback处理类哪个方法来处理java异常/业务异常
     */
    //这里我们使用全局限流处理类,显示限流信息
    @GetMapping("/t6")
    @SentinelResource(value = "t6",
            fallbackClass = CustomGlobalFallbackHandler.class,
            fallback = "fallbackHandlerMethod1",
            blockHandlerClass = CustomGlobalBlockHandler.class,
            blockHandler = "handlerMethod1"
                     )
    public Result t6() {
        //假定: 当访问t6资源次数是5的倍数时,就出现java异常
        if (++num % 5 == 0) {
            throw new NullPointerException("null指针异常 num=" + num);
        }
 

        log.info("执行t6() 线程id={}", Thread.currentThread().getId());
        return Result.success("200", "t6()执行OK~~");
    }

测试

1 启动Nacos Server 8848

2 启动Sentinel8080 控制台/Sentinel dashboard

3 启动member-service-nacos-provider-10004

4 浏览器: http://localhost:10004/t6

浏览器输入: http://localhost:10004/t6 , 访问次数不是5 的倍数, 返回正常结果

image.png

  1. 浏览器输入: http://localhost:10004/t6 , 访问次数是5 的倍数, 返回fallback 指定方法信息

image.png

  1. 为资源/t6 增加流控规则,方便测试

image.png

image.png

  1. 在流控规则菜单,可以看到新增规则

image.png

  1. 浏览器输入: http://localhost:10004/t6 , 如果访问QPS 大于1 , 由blockHandler 指定的方法处理,访问次数是5 的倍数, 由fallback 指定方法处理, 其它情况返回正常的结果.

image.png

image.png

image.png

exceptionsToIgnore

如果希望忽略某个异常,可以使用exceptionsToIgnore

    /**
     * value = "t6" 表示 sentinel限流资源的名字
     * blockHandlerClass = CustomGlobalBlockHandler.class : 全局限流处理类
     * blockHandler = "handlerMethod1": 指定使用全局限流处理类哪个方法,来处理限流信息
     * fallbackClass = CustomGlobalFallbackHandler.class: 全局fallback处理类
     * fallback = "fallbackHandlerMethod1": 指定使用全局fallback处理类哪个方法来处理java异常/业务异常
     * exceptionsToIgnore = {RuntimeException.class}: 表示如果t6()抛出RuntimeException, 就使用系统默认方式处理
     */
    //这里我们使用全局限流处理类,显示限流信息
    @GetMapping("/t6")
    @SentinelResource(value = "t6",
            fallbackClass = CustomGlobalFallbackHandler.class,
            fallback = "fallbackHandlerMethod1",
            blockHandlerClass = CustomGlobalBlockHandler.class,
            blockHandler = "handlerMethod1",
                          //注意 这个之所以是NullPointerException.class的原因是RuntimeException异常包括NullPointerException如果写RuntimeException异常那么NullPointerException异常也会捕获到那就没意义了
            exceptionsToIgnore = {NullPointerException.class})
    public Result t6() {
        //假定: 当访问t6资源次数是5的倍数时,就出现java异常
        if (++num % 5 == 0) {
            throw new NullPointerException("null指针异常 num=" + num);
        }
        if (num % 6 == 0) {//当访问t6资源次数是6的倍数时,抛出 runtime异常
            throw new RuntimeException("RuntimeException num=" + num);
        }

        log.info("执行t6() 线程id={}", Thread.currentThread().getId());
        return Result.success("200", "t6()执行OK~~");
    }
  1. 浏览器输入: http://localhost:10004/t6 , 你会发现访问次数为5 的倍数时,不再调用fallback 指定方法处理

在Sentinel中t6增加流控 这时就有4种方法

image.png

  1. 正常执行

image.png

  1. 访问过快被blockHandler限流捕获到

image.png

  1. 这个是忽略的异常

image.png

  1. 这个是被fallback捕获的异常

image.png

接入Sentinel 的方式

10.8.4.1 代码方式(硬编码,侵入性强, 不推荐)

  1. 文档地址: https://github.com/alibaba/Sentinel/wiki/介绍
  2. 基本使用

image.png

image.png

image.png

注解方式(低侵入性, 前面用过, 推荐)

  1. 注解方式埋点不支持private 方法
    https://xue.baidu.com/okam/pages/strategy-tp/index?strategyId=136707206360879&source=natural
  2. @SentinelResource 用于定义资源,并提供可选的异常处理和fallback 配置项。

@SentinelResource 注解包含以下属性(我们再梳理一下)

  1. value:资源名称,必需项(不能为空)

  2. entryType:entry 类型,可选项(默认为EntryType.OUT)

  3. blockHandler / blockHandlerClass: blockHandler 对应处理BlockException 的函数名称,可选项。blockHandler 函数访问范围需要是public,返回类型需要与原方法相匹配,参数类型需要和原方法相匹配并且最后加一个额外的参数,类型为BlockException。blockHandler 函数默认需要和原方法在同一个类中。若希望使用其
    他类的函数,则可以指定blockHandlerClass 为对应的类的Class 对象,注意对应的函数必需为static 函数,否则无法解析。

  4. fallback / fallbackClass:fallback 函数名称,可选项,用于在抛出异常的时候提供fallback 处理逻辑。fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore里面排除掉的异常类型)进行处理。fallback 函数签名和位置要求:
    (1)返回值类型必须与原函数返回值类型一致;
    (2)方法参数列表需要和原函数一致,或者可以额外多一个Throwable 类型的参数用于接收对应的异常。
    (3)fallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定fallbackClass 为对应的类的Class 对象,注意对应的函数必需为static 函数,否则无法解析。

  5. defaultFallback(since 1.6.0):默认的fallback 函数名称,可选项,通常用于通用的
    fallback 逻辑(即可以用于很多服务或方法)。默认fallback 函数可以针对所有类型的异常(除了exceptionsToIgnore 里面排除掉的异常类型)进行处理。若同时配置了fallback 和defaultFallback,则只有fallback 会生效。defaultFallback 函数签名要求:
    (1)返回值类型必须与原函数返回值类型一致;
    (2)方法参数列表需要为空,或者可以额外多一个Throwable 类型的参数用于接收对应的异常。
    (3)defaultFallback 函数默认需要和原方法在同一个类中。若希望使用其他类的函数,则可以指定fallbackClass 为对应的类的Class 对象**,注意对应的函数必需为static 函数,否则无法解析。**

  6. exceptionsToIgnore(since 1.6.0):用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入fallback 逻辑中,而是会原样抛出。

openFeign+sentinel 对远程调用熔断降级

当前微服务基础环境

测试

1 启动Nacos Server 8848

2 启动member-service-nacos-provider-10004/10006

3 启动member-service-nacos-consumer-80

4 浏览器: http://localhost/member/nacos/consumer/get/1

浏览器输入: http://localhost/member/nacos/consumer/get/1 , 目前是Ribbon+RestTemplate

image.png

image.png

服务消费者整合Openfeign

需求分析/图解

需求:在member-service-nacos-consumer-80 整合Openfeign 实现远程调用

image.png

代码+配置实现步骤

  1. 修改member-service-nacos-consumer-80 的pom.xml 加入openfeign 依赖
<!-- 引入openfeign -->
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  1. 在member-service-nacos-consumer-80 创建/springcloud/service/MemberOpenFeignService.java接口
@FeignClient(value = "member-service-nacos-provider")
public interface MemberOpenFeignService {
    /**
     * 解读
     * 1. 远程调用方式是 get
     * 2. 远程调用的url 为 http://member-service-nacos-provider/member/get/{id}
     * 3. member-service-nacos-provider是nacos注册中心服务名
     * 4. openfeign会根据负载均衡算法来决定调用的是 10004/10006,默认是轮询算法
     * 5. openfeign是通过接口方式调用服务
     */
    @GetMapping("/member/get/{id}")
    public Result getMemberById(@PathVariable("id") Long id);
}

  1. 修改controller/MemberNacosConsumerController.java , 增加方法
    //装配MemberOpenFeignService
    @Resource
    private MemberOpenFeignService memberOpenFeignService;

    //编写方法通过openfeign实现远程调用
    @GetMapping("/member/openfeign/consumer/get/{id}")
    public Result<Member> getMemberOpenfeignById(@PathVariable("id") Long id) {
        //这里我们使用openfeign接口方式远程调用
        log.info("调用方式是 openfeign..");
        return memberOpenFeignService.getMemberById(id);
    }
  1. 在member-service-nacos-consumer-80 的主启动类加入注解
@SpringBootApplication
@EnableDiscoveryClient //引入的是启动 nacos发现注解
@EnableFeignClients
public class MemberNacosConsumerApplication80 {
    public static void main(String[] args) {

        SpringApplication.run(MemberNacosConsumerApplication80.class,args);
    }
}

测试

1 启动Nacos Server 8848

2 启动member-service-nacos-provider-10004/10006

3 启动member-service-nacos-consumer-80

4 浏览器: http://localhost/member/openfeign/consumer/get/1

浏览器输入: http://localhost/member/openfeign/consumer/get/1 , 目前是Openfeign调用(负载均衡)

image.png

服务消费者整合Sentinel

需求分析/图解

需求:在member-service-nacos-consumer-80 整合Sentinel 能被Sentinel 监控

image.png

代码+配置实现步骤

  1. 修改member-service-nacos-consumer-80 的pom.xml 加入sentinel 依赖
<!-- 引入alibaba-sentinel -->
<dependency>
	<groupId>com.alibaba.cloud</groupId>
	<artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
  1. 修改member-service-nacos-consumer-80 的application.yml 配置sentinel
server:
  port: 80

spring:
  application:
    name: member-service-nacos-consumer-80
  #配置nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos server的地址
    sentinel:
      transport:
        dashboard: localhost:8080 #指定sentinel控制台地址(dash board)
        port: 8719 #设置端口默认是 8719, 如果该端口被占用, 就自动从 8791+1进行扫描, 直到找到一个没有占用的端口
#设置暴露所有的监控点
management:
  endpoints:
    web:
      exposure:
        include: '*'

测试

1 启动Nacos Server 8848

2 启动Sentinel8080 控制台/Sentinel dashboard

3 启动member-service-nacos-provider-10004/10006

4 启动member-service-nacos-consumer-80

5 浏览器: http://localhost/member/openfeign/consumer/get/1

  1. 目前是Openfeign调用(负载均衡)

image.png

  1. 登录sentinel 控制台: 可以看到已经监控到member-service-nacos-consumer

image.png

openFeign+sentinel 对远程调用熔断降级

需求分析/图解

  1. 需求/如图:在member-service-nacos-consumer-80 调用某个无效服务时,启动Sentinel的熔断降级机制, 能够快速返回响应,而不是使用默认的超时机制(因为超时机制容易线
    程堆积, 从而导致雪崩)

image.png

  1. 先测试一下,关闭10004/10006, 这时openfeign 去调用会怎么样? (返回time out)

image.png

  1. 还可以测试一下,让10004 服务对应的API 执行时间很长(比如休眠2 秒), 这时openfeign 去调用会怎么样?

image.png

代码+配置实现步骤

  1. 修改member-service-nacos-consumer-80 的service/MemberOpenFeignService.java接口, 加入fallback 的处理类
@FeignClient(value = "member-service-nacos-provider", fallback = MemberFeignFallbackService.class)
public interface MemberOpenFeignService {
    /**
     * 解读
     * 1. 远程调用方式是 get
     * 2. 远程调用的url 为 http://member-service-nacos-provider/member/get/{id}
     * 3. member-service-nacos-provider是nacos注册中心服务名
     * 4. openfeign会根据负载均衡算法来决定调用的是 10004/10006,默认是轮询算法
     * 5. openfeign是通过接口方式调用服务
     */
    @GetMapping("/member/get/{id}")
    public Result getMemberById(@PathVariable("id") Long id);
}

  1. 创建MemberFeignFallbackService.java
@Component
public class MemberFeignFallbackService
        implements MemberOpenFeignService {
    @Override
    public Result getMemberById(Long id) {
        return Result.error("500", "被调用服务异常, 熔断降级, 快速返回结果,防止线程堆积..");
    }
}

  1. 修改member-service-nacos-consumer-80 的application.yml , 加入openfeign 和sentinel 整合配置
server:
  port: 80

spring:
  application:
    name: member-service-nacos-consumer-80
  #配置nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos server的地址
    sentinel:
      transport:
        dashboard: localhost:8080 #指定sentinel控制台地址(dash board)
        port: 8719 #设置端口默认是 8719, 如果该端口被占用, 就自动从 8791+1进行扫描, 直到找到一个没有占用的端口
#设置暴露所有的监控点
management:
  endpoints:
    web:
      exposure:
        include: '*'
#openfeign和sentinel整合,必须配置
feign:
  sentinel:
    enabled: true

测试

1 启动Nacos Server 8848

2 启动Sentinel8080 控制台/Sentinel dashboard

3 关闭member-service-nacos-provider-10004/10006

4 启动member-service-nacos-consumer-80

5 浏览器: http://localhost/member/openfeign/consumer/get/1

浏览器输入: <http://localhost/member/openfeign/consumer/get/1> , 目前是Openfeign调用(负载均衡)

image.png

注意事项和细节说明

  1. 因为member-service-nacos-consumer-80 已经被sentinel 监控,所以我们可以加入相关的流控规则, 比如为/member/openfeign/consumer/get/1 加入流控规则qps = 1

image.png

测试: 如果/member/openfeign/consumer/get/1 请求QPS 超过1, 会输出

image.png

QPS 没有超过1, 会被fallback 处理, 如图

image.png
2. 如果远程服务恢复正常, 又会正常调用

规则持久化

规则没有持久化的问题

1 如果sentinel 流控规则没有持久化,当重启调用API/接口所在微服务后,规则就会丢失,需要重新加入
2 解决方案:通过Nacos 进行持久化

规则持久化方案

  1. 阿里云Ahas[最方便/付费]

    官方文档:https://help.aliyun.com/product/87450.html?spm=5176.cnahas.0.0.78034bb7ef0y86

image.png

  1. 在Nacos Server 配置规则, 完成持久化-官方推荐

  2. 将规则持久化到本地文件, 定时同步

  3. 其它…

Nacos Server 配置中心-规则持久化实例

工作原理示意图

image.png

需求分析/图解

  1. 需求: 为member-service-nacos-consumer-80 微服务的/member/openfeign/consumer/get/1 API 接口添加流控规则QPS=1/快速失败.
  2. 要求将该流控规则加入到nacos server 配置中心,实现持久化

image.png

[
	{
		"resource":"/member/openfeign/consumer/get/1",
		"limitApp": "default",
		"grade": 1,
		"count": 1,
		"strategy": 0,
		"controlBehavior": 0,
		"clusterMode": false
	}
]

image.png

  1. 在Nacos Server 配置中心增加Sentinel 客户端/微服务模块的流控规则参数说明
  • resource∶资源名称;
  • limlitApp∶ 来源应用;
  • grade∶阈值类型,0表示线程数,1表示QPS;
  • count∶单机阈值;
  • strategy∶流控模式,0表示直接,1表示关联,2表示链路;
  • controlBehavior∶流控效果,0表示快速失败,1表示Warm Up,2表示排队等待;
  • clusterMode∶是否集群
  1. 修改member-service-nacos-consumer-80 的pom.xml, 加入加入sentinel 和nacos持久化整合依赖
<!-- 加入sentinel 和nacos 持久化整合依赖-->
<dependency>
	<groupId>com.alibaba.csp</groupId>
	<artifactId>sentinel-datasource-nacos</artifactId>
</dependency>
  1. 修改member-service-nacos-consumer-80 的application.yml , 配置该微服务从NacosServer 获取流控规则
server:
  port: 80

spring:
  application:
    name: member-service-nacos-consumer-80
  #配置nacos
  cloud:
    nacos:
      discovery:
        server-addr: localhost:8848 #nacos server的地址
    sentinel:
      transport:
        dashboard: localhost:8080 #指定sentinel控制台地址(dash board)
        port: 8719 #设置端口默认是 8719, 如果该端口被占用, 就自动从 8791+1进行扫描, 直到找到一个没有占用的端口
      datasource:
        ds1:
          #流控规则配置是从nacos server 配置中心获取
          nacos:
            server-addr: localhost:8848 #指定nacos server 配置中心地址
            dataId: member-service-nacos-consumer #nacos server 配置中心 dataId
            groupId: DEFAULT_GROUP #指定组[nacos server配置中心]
            data-type: json #指定配置流控规则的数据类型
            rule-type: flow #规则类型: 流控规则 表示一会看文档
#设置暴露所有的监控点
management:
  endpoints:
    web:
      exposure:
        include: '*'
#openfeign和sentinel整合,必须配置
feign:
  sentinel:
    enabled: true

测试

1 启动Nacos Server 8848

2 启动Sentinel8080 控制台/Sentinel dashboard

3 启动member-service-nacos-provider-10004/10006

4 启动member-service-nacos-consumer-80

5 浏览器: http://localhost/member/openfeign/consumer/get/1

  1. 浏览器输入: http://localhost/member/openfeign/consumer/get/1 , 目前是Openfeign调用(负载均衡), 而且流控规则已经生效了.

image.png
2. 注意看sentinel, 这个流控规则已经生成了.

image.png

  1. 查看Sentinel 控制台, 发现已经同步了流控规则

image.png

注意事项和细节

  1. 在nacos server 配置sentinel 流控规则的Data ID 也可以自己指定,比如写成wyx-id,只要在sentinel client/微服务的applicaion.yml 的datasource.ds1.nacos.dataId 的值保持一致即可
  2. 如图所示

image.png

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

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

相关文章

Docker从入门到会搭建一个简单的系统

一、环境准备 1、查看Llinux的版本 [rootlocalhost ~]# cat /etc/redhat-release 2、关闭防火墙 [rootlocalhost ~]# systemctl stop firewalld.service 3、设置开机不启动防火墙 [rootlocalhost ~]# systemctl disable firewalld.service 二、Docker的安装 1、Docker是中高…

单片机GD32F303RCT6 (Macos环境)开发 (三十二)—— GD32 SPI主从实验 中断模式

GD32 SPI主从实验 中断模式 1、接线 SPI0 PA4 PA5 PA6 PA7SPI1 PB12 PB14 PB14 PB15采用全双工模式SPI0 SPI1CS PA4----------------PB12CLK PA5----------------PB13MISO PA6----------------PB14MOSI PA7----------------PB152、spi0 主设…

chatgpt赋能python:Python简单游戏开发入门

Python简单游戏开发入门 Python作为一门流行的编程语言&#xff0c;可以用来开发各种各样的应用&#xff0c;包括游戏。虽然Python不是游戏开发的主流语言&#xff0c;但我们可以用它来制作一些简单而有趣的游戏。在这篇文章中&#xff0c;我们将介绍如何用Python创建一个简单…

批量剪辑视频工具源码开发搭建分享

搭建步骤 1. 首先需要根据自身产品确定视频类型及需要实现的视频效果 2. 根据预期视频效果选择视频上传模式&#xff0c;并将视频素材进行上传 3. 添加音频、字幕&#xff0c;标题等与素材进行组合。 4. 设置投放计划&#xff0c;包括&#xff1a;视频标题、视频话题等 5.…

Are Emergent Abilities of Large Language Models a Mirage?

Paper name Are Emergent Abilities of Large Language Models a Mirage? Paper Reading Note Paper URL: https://arxiv.org/pdf/2304.15004.pdf Video URL: https://www.youtube.com/watch?vhZspGdApDIo TL;DR 2023 年斯坦福的研究&#xff0c;探索大语言模型表现出涌…

LeetCode 1552. Magnetic Force Between Two Balls【二分,排序,贪心】中等

本文属于「征服LeetCode」系列文章之一&#xff0c;这一系列正式开始于2021/08/12。由于LeetCode上部分题目有锁&#xff0c;本系列将至少持续到刷完所有无锁题之日为止&#xff1b;由于LeetCode还在不断地创建新题&#xff0c;本系列的终止日期可能是永远。在这一系列刷题文章…

内存栈与CPU栈机制

1. 内存栈: 先入后出,LIFO(LAST IN FIRST OUT) 入栈:将一个新的元素放到栈顶 出栈:从栈顶取出一个元素 栈顶元素总是最后一个入栈,需要时出栈. 2.CPU栈机制 8086CPU提供相关指令以栈方式来访问内存空间.相当于将一段内存当做栈来使用 8086CPU提供的入栈指令为:PUSH ,出栈指令为…

【Linux】序列化和反序列化

目录 &#x1f308;前言&#x1f338;1、应用层&#x1f33a;2、重谈协议&#x1f341;3、网络计算器&#x1f361;3.1、定制协议&#x1f362;3.2、样例代码 &#x1f308;前言 这篇文章给大家带来序列化和反序列化的学习&#xff01;&#xff01;&#xff01; &#x1f338;…

chatgpt赋能python:Python倒序for:如何优化循环遍历

Python倒序for&#xff1a;如何优化循环遍历 Python作为一门高级编程语言&#xff0c;一直以来都在开发者中得到广泛的应用。在日常的编程工作中&#xff0c;遍历列表&#xff08;List&#xff09;和元组&#xff08;Tuple&#xff09;是很常见的操作。而对于列表或元组的倒序…

NLP(五十四)tiktoken的使用

tiktoken是OpenAI于近期开源的Python第三方模块&#xff0c;该模块主要实现了tokenizer的BPE&#xff08;Byte pair encoding&#xff09;算法&#xff0c;并对运行性能做了极大的优化。本文将介绍tiktoken模块的使用。 tiktoken简介 BPE(Byte pair encoding)算法是NLP中常见的…

Redis系列---Redis网络模型1

我们都知道&#xff0c;redis的高性能是具有多方面的因数&#xff0c;如&#xff1a;运行在内存上&#xff0c;单线程命令&#xff0c;io多路复用技术等&#xff0c;对于redis高性能的探究&#xff0c;就需要深入的研究其工作原理&#xff0c;这就涉及到redis的网络模型了&…

python实现单链表、双链表、反转链表(二)

一、链表概述 链表是有元素组成的数据结构&#xff0c;每个元素都是单独对象&#xff0c;包含数据和指针信息 链表中的每个元素称为节点&#xff0c;如下所示&#xff0c;第一个节点称为Head(头节点)&#xff0c;为链表的入口点&#xff0c;如果链表为空&#xff0c;则Head指…

Vue.js 比较重要知识点总结二

概述 vue3 组合式API生命周期钩子函数有变化吗&#xff1f;Composition API 与 Options API 有什么区别&#xff1f;watch 和 watchEffect 的区别&#xff1f;vue2 如何升级到 vue3 ? vue3 组合式API生命周期钩子函数有变化吗&#xff1f; 选项式API 和 组合式API 生命周期…

Java的继承性

1.为什么要有类的继承性&#xff1f;(继承性的好处&#xff09; ① 减少了代码的冗余&#xff0c;提高了代码的复用性② 便于功能的扩展③ 为之后多态性的使用&#xff0c;提供了前提 2.子类继承父类以后有哪些不同&#xff1f; 2.1体现&#xff1a; 一旦子类A继承父类B以…

汇编基础学习

1. 利用ldr向寄存器里面写较大数据&#xff0c;和设置寄存器的某些位 2. 这个lable 不对呢 验证宏值加载到寄存器里是正确的。 pc 的地址是0x80594 当前pc指针加上宏定义值的地址值。 3 打印字符串 字符串加载了8个字节到寄存器里面&#xff0c; 如何调试打印出来呢&#xff1…

数据库设计的原则有哪些

数据库设计是程序开发的核心部分&#xff0c;标准的数据库设计原则和步骤能有效提高开发进度和效率。 数据库设计(Database Design)是指对于一个给定的应用环境&#xff0c;构造最优的数据库模式&#xff0c;建立数据库及其应用系统&#xff0c;使之能够有效地存储数据&#xf…

RK3588平台开发系列讲解(驱动基础篇)中断相关函数

平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、获取中断号相关函数二、申请中断函数三、free_irq 函数四、中断处理函数五、中断使能和禁止函数沉淀、分享、成长,让自己和他人都能有所收获!😄 📢 Linux 中断有专门的中断子系统,其实现原理很复杂,但是驱…

Git详解——安装、使用、搭建、IDEA集成

Git 看目录&#xff0c;越往后面越重要 目录一、git是什么&#xff1f;二、为什么要使用Git&#xff1f;三、版本控制工具四、git下载安装以及环境配置五、git基本命令六、git项目搭建七、远程仓库怎么搞&#xff1f;git,gitlab,github,gitee区别八、idea集成Git 一、Git是什…

HBase2.2.2安装(单机、伪分布)

系列文章目录 Ubuntu常见基本问题 Hadoop3.1.3安装&#xff08;单机、伪分布&#xff09; Hadoop集群搭建 HBase2.2.2安装&#xff08;单机、伪分布&#xff09; Zookeeper集群搭建 文章目录 系列文章目录前置条件一、HBase2.2.2安装二、配置环境变量1、问题 三、单机模式1、修…

浅谈数字化

一、数字化转型 数字化转型&#xff08;Digital transformation&#xff09;是建立在数字化转换&#xff08;Digitization&#xff09;、数字化升级&#xff08;Digitalization&#xff09;基础上&#xff0c;进一步触及公司核心业务&#xff0c;以新建一种商业模式为目标的高…