SpringCloudAlibaba:服务容错之Sentinel学习

news2024/11/24 11:24:14

目录

一、高并发带来的问题

服务雪崩效应

二、常见容错方案

(一)隔离

(二)超时

(三)限流

(四)熔断

(五)降级

三、常见的容错组件

四、Sentinel概述

(一)Sentinel 特征:

(二)两个重要概念

五、安装Sentinel控制台

1、下载jar包,上传到服务器

2、编写启动脚本(根据官网启动命令)

六、Sentinel规则

(一)流量控制规则

1、QPS流控

2、并发线程数

(二)隔离与降级

1、Feign整合Sentinel

2、线程隔离

(三)熔断降级规则

1.慢调用比例 (SLOW_REQUEST_RATIO):

2.异常比例 (ERROR_RATIO):

3.异常数 (ERROR_COUNT):

(四)热点规则

七、Sentinel规则持久化

一、概念

二、如何持久化?

1.添加 pom 依赖

2.修改 yml 配置文件,添加 Nacos 数据源配置

3.Nacos 配置管理

三、yml 配置详解(与 Ncaos 整合)

四、json 参数详解

1、流控规则

2、降级规则

3、热点规则

4、系统规则

5、授权规则

五、持久化过程中碰到的错误


一、高并发带来的问题

在微服务架构中,我们将业务拆分成一个个的服务,服务与服务之间可以相互调用,但是由于网络原因或者自身的原因,服务并不能保证服务的100%可用,如果单个服务出现问题,调用这个服务就会出现网络延迟,此时若有大量的网络涌入,会形成任务堆积,最终导致服务瘫痪。

服务雪崩效应

在分布式系统中,由于网络原因或自身的原因,服务一般无法保证 100% 可用。如果一个服务出现了问题,调用这个服务就会出现线程阻塞的情况,此时若有大量的请求涌入,就会出现多条线程阻塞等待,进而导致服务瘫痪。 由于服务与服务之间的依赖性,故障会传播,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的 “雪崩效应” 。

二、常见容错方案

要防止雪崩的扩散,我们就要做好服务的容错,容错说白了就是保护自己不被猪队友拖垮的一些措 施, 下面介绍常见的服务容错思路和组件。 常见的容错思路: 常见的容错思路有隔离、超时、限流、熔断、降级这几种,下面分别介绍一下。

(一)隔离

它是指将系统按照一定的原则划分为若干个服务模块,各个模块之间相对独立,无强依赖。当有故 障发生时,能将问题和影响隔离在某个模块内部,而不扩散风险,不波及其它模块,不影响整体的 系统服务。常见的隔离方式有:线程池隔离和信号量隔离.

(二)超时

在上游服务调用下游服务的时候,设置一个最大响应时间,如果超过这个时间,下游未作出反应, 就断开请求,释放掉线程。

(三)限流

限流就是限制系统的输入和输出流量已达到保护系统的目的。为了保证系统的稳固运行,一旦达到 的需要限制的阈值,就需要限制流量并采取少量措施以完成限制流量的目的。

(四)熔断

在互联网系统中,当下游服务因访问压力过大而响应变慢或失败,上游服务为了保护系统整 体的可用性,可以暂时切断对下游服务的调用。这种牺牲局部,保全整体的措施就叫做熔断。

服务熔断一般有三种状态:

熔断关闭状态(Closed): 服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制

熔断开启状态(Open):后续对该服务接口的调用不再经过网络,直接执行本地的fallback方法

半熔断状态(Half-Open):尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。如果成功率达到预期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断关闭状 态。

(五)降级

降级其实就是为服务提供一个托底方案,一旦服务无法正常调用,就使用托底方案。

三、常见的容错组件

Hystrix

Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或者第三方库,防止 级联失败,从而提升系统的可用性与容错性。

Resilience4J

Resilicence4J一款非常轻量、简单,并且文档非常清晰、丰富的熔断工具,这也是Hystrix官方推 荐的替代产品。不仅如此,Resilicence4j还原生支持Spring Boot 1.x/2.x,而且监控也支持和 prometheus等多款主流产品进行整合。

Sentinel

Sentinel 是阿里巴巴开源的一款断路器实现,本身在阿里内部已经被大规模采用,非常稳定。

四、Sentinel概述

Sentinel (分布式系统的流量防卫兵) 是阿里开源的一套用于服务容错的综合性解决方案。它以流量 为切入点, 从流量控制、熔断降级、系统负载保护等多个维度来保护服务的稳定性。

Sentinel 分为两个部分:

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

  • 控制台(Dashboard)基于 Spring Boot 开发,打包后可以直接运行,不需要额外的 Tomcat 等 应用容器

(一)Sentinel 特征:

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

(二)两个重要概念

1、资源 资源就是Sentinel要保护的东西;资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,可以是一个服务,也可以是一个方法,甚至可以是一段代码。

2、规则 规则就是用来定义如何进行保护资源的 作用在资源之上, 定义以什么样的方式保护资源,主要包括流量控制规则、熔断降级规则以及系统 保护规则。

五、安装Sentinel控制台

1、下载jar包,上传到服务器

您可以从 release 页面 下载您需要的班版本的控制台 jar 包。

2、编写启动脚本(根据官网启动命令)

将jar包上传至服务器,并在同一目录下创建启动脚本start.sh,内容如下:

  1. 创建start.sh

    [root@localhost sentinel]# touch start.sh  
  2. 编辑start.sh文件(使用命令或者使用Xtfp软件进行编辑)

    [root@localhost sentinel]# vim start.sh

    将下面内容复制到文件中,如若8081端口冲突,可使用 -Dserver.port=新端口 进行设置。

    rm -rf /sentinel/sentinel.log
    nohup java -Dserver.port=8081 -Dcsp.sentinel.dashboard.server=localhost:8081 -Dproject.name=sentinel-dashboard -jar sentinel-dashboard-1.8.6.jar > /sentinel/sentinel.log 2>&1 &
  3. 给予权限

    [root@localhost sentinel]# chmod 777 start.sh
  4. 启动sentinel控制台

    [root@localhost sentinel]# ./start.sh
  5. 访问控制台:192.168.XXX.XXX:8081 (Linux系统IP地址,可使用 ip a 命令查看) 进行访问

    username:sentinel    password:sentinel

  

六、Sentinel规则

(一)流量控制规则

流量控制,其原理是监控应用流量的QPS(每秒查询率) 或并发线程数等指标,当达到指定的阈值时对流量进行控制,以避免被瞬时的流量高峰冲垮,从而保障应用的高可用性。

项目中引入jar包

<dependency>
    <groupId>com.alibaba.cloud</groupId>
    <artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>

1、QPS流控

(1)yml文件配置

spring:
  cloud:
    sentinel: # 服务容错
      transport:
        dashboard: 192.168.177.129:8081
        port: 8719
​

(2)定义资源

@RestController
@RefreshScope // 在需要动态读取配置的类上添加此注解就可以(动态配置刷新)
@RequestMapping("/user")
public class UserController {    
    @RequestMapping("/get1")
    @SentinelResource(value = "/resource/user/get1", blockHandler = "blockHandlerForGet1")
    public Integer get1(){
        return 111111;
    }
​
    public Integer blockHandlerForGet1(BlockException ex) {
        return 999999;
    }
}    
​

(3)启动项目,发送请求(http://localhost:端口号/user/get1)

(4)定义限流规则 点击簇点链路,我们就可以看到访问过的接口地址,然后点击对应的(@SentinelResource注解的value的值)流控按钮,进入流控规则配置页面。新增流控规则界面如下:

  • 资源名: 唯一名称,默认是请求路径,可自定义

  • 针对来源: 指定对哪个微服务进行限流,默认指default,意思是不区分来源,全部限制 阈值类型/单机阈值:

    QPS(每秒请求数量): 当调用该接口的QPS达到阈值的时候,进行限流。 线程数:当调用该接口的线程数达到阈值的时候,进行限流。

  • 是否集群:暂不需要集群

(5)效果

再快速通过网页发送多次请求,会发现每秒只有两次是get1结果,其余超出的都是blockHandlerForGet1的结果。

2、并发线程数

Sentinel并发控制是指使用Sentinel来限制接口的最大并发访问量。Sentinel并发控制不负责创建和管理线程池,而是简单统计当前请求上下文的线程数且(正在执行的调用数目),如果超出阈值,新的请求会被立即拒绝,效果类似于信号量隔离。并发数控制通常在调用端进行配置。

(1)定义资源

@RequestMapping("/get1")
@SentinelResource(value = "/resource/user/get1", blockHandler = "blockHandlerForGet1")
public Integer get1(){
    try {
        Thread.sleep(5000);
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
    return 666666;
}
//   blockHandler 函数会在原方法被限流/降级/系统保护的时候调用
public Integer blockHandlerForGet1(BlockException ex){
    return 999999;
}
​

(2)定义限流规则

(3)测试

使用Postman进行测试,建立多个请求,都发送请求进行测试。

3、流控模式

sentinel共有三种流控模式,分别是:

  • 直接(默认):接口达到限流条件时,开启限流

  • 关联:当关联的资源达到限流条件时,开启限流 [适合做应用让步]

  • 链路:当从某个接口过来的资源达到限流条件时,开启限流

4、流控效果

在Sentinel中,当流控规则生效时,会对超出阈值的请求进行限流处理。常见的限流策略有:

  1. 直接拒绝:直接拒绝超出阈值的请求,返回限流提示。

  2. 慢启动(Warm Up):它从开始阈值到最大QPS阈值会有一个缓冲阶段,一开始的阈值是最大QPS阈值的1/3,然后慢慢增长,直到最大阈值,适用于将突然增大的流量转换为缓步增长的场景。

    举个例子,阀值为10,预热时长设置5秒。 系统初始化的阀值为10 / 3约等于3,即阀值刚开始为3,然后过了 5秒后阀值才慢慢升高恢复到10。

  3. 排队等待:超出阈值的请求会加入等待队列,当阈值允许时依次放行,如果等待超时则拒绝。

(二)隔离与降级

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

1、Feign整合Sentinel

  1. 修改application.yml开启Feign的Sentinel功能

    feign:
      sentinel:
        enabled: true
    ​
  2. 创建feign远程调用接口

    @FeignClient(value = "order-server",path = "/order")
    public interface OrderFeign {
        
        @GetMapping("/get1")
        Integer get1();
    }
    ​
  3. 给feignClient编写失败后的降级逻辑 方式一:FallbackClass 无法对远程调用的异常做处理 方式二:FallbackFactory 可以对远程调用的异常做处理

    public class UserClientFallbackFactory implements FallbackFactory<OrderFeign> {
        @Override
        public OrderFeign create(Throwable cause) {
            return new OrderFeign() {
                @Override
                public Integer get1() {
                    return 123456;
                }
            };
        }
    }
    ​
  4. 将降级工程注册为一个Bean

    @Configuration
    public class SentinelConfig {
        @Bean
        public UserClientFallbackFactory userClientFallbackFactory(){
            return new UserClientFallbackFactory();
        }
    }
    ​
  5. 给feign远程调用接口指定降级工厂

    @FeignClient(value = "order-server",path = "/order",fallbackFactory = UserClientFallbackFactory.class)
    public interface OrderFeign {
    ​
        @GetMapping("/get1")
        Integer get1();
    }
    ​

2、线程隔离

线程隔离有两种实现方式:

  • 线程池隔离

  • 信号量隔离(Sentinel默认采用)

(三)熔断降级规则

现代微服务架构都是分布式的,由非常多的服务组成。不同服务之间相互调用,组成复杂的调用链路。以上的问题在链路调用中会产生放大的效果。复杂链路上的某一环不稳定,就可能会层层级联,最终导致整个链路都不可用。因此我们需要对不稳定的弱依赖服务调用进行熔断降级,暂时切断不稳定调用,避免局部不稳定因素导致整体的雪崩。熔断降级作为保护自身的手段,通常在客户端(调用端)进行配置。

熔断策略:

1.慢调用比例 (SLOW_REQUEST_RATIO):

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

解读:如果在统计时长10秒内,发送的请求超过10个,并且其中百分之50(比例阈值)的请求时间超过了500ms(最大RT),则触发熔断,熔断时长为5s,在5s时间之内所有请求都将无法访问,等进入half-open状态,放行一次请求进行测试。

2.异常比例 (ERROR_RATIO):

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

3.异常数 (ERROR_COUNT):

当单位统计时长内的异常数目超过阈值之后会自动进行熔断。经过熔断时长后熔断器会进入探测恢复状态(HALF-OPEN 状态),若接下来的一个请求成功完成(没有错误)则结束熔断,否则会再次被熔断。注意由于统计时间窗口是分钟级别的,若时间窗口小于 60s,则结束熔断状态后仍可能再进入熔断状态。

(四)热点规则

// 测试热点规则
@RequestMapping("/get2")
@SentinelResource(value = "/resource/user/get2", blockHandler = "blockHandlerForTest")
public Integer get2(@RequestParam("id") Integer id){
	return 666666;
}

public Integer blockHandlerForTest(Integer id, BlockException ex) {
	return 999999;
}

七、Sentinel规则持久化

push模式:控制台将配置规则推送到远程配置中心,例如Nacos。Sentinel客户端监听Nacos,获取配置变更的推送消息,完成本地配置更新。

一、概念

当应用重启后,Sentinel 规则就消失了,生产环境需要将配置的规则进行持久化

二、如何持久化?

将限流、熔断配置规则持久化进 Nacos 保存,只要刷新被监控的应用,Sentinel 控制台的流控规则就能看到,持久化后无需重新配置才能看到。只要 Nacos 里面的配置不删除,针对该应用的Sentinel上的流控规则持续有效。

1.添加 pom 依赖

<dependency>
    <groupId>com.alibaba.csp</groupId>
    <artifactId>sentinel-datasource-nacos</artifactId>
</dependency>

2.修改 yml 配置文件,添加 Nacos 数据源配置

spring:
   cloud:
    sentinel:
      # Sentinel 规则持久化
      datasource:
        # 自定义命名
        flow-rule:
          # 支持多种持久化数据源:file、nacos、zk、apollo、redis、consul
          nacos:
            username: nacos
            password: nacos
            # nacos服务地址
            server-addr: 192.168.177.129:8848
            # 命名空间,根据环境配置
            # namespace: public
            # 这里我做了一下细分,不同规则设置不同groupId
            group-id: USER_SENTINEL_FLOW_GROUP
            # 仅支持JSON和XML类型
            data-id: ${spring.application.name}.yaml
            # 规则类型:flow(流)、degrade(降级)、param-flow(参数流)、system(系统)、authority(权限)
            rule-type: flow
            data-type: json

3.Nacos 配置管理

流控规则持久化配置参数说明:

resource:资源名。 limitApp:来源应用。 grade:阈值类型。0 表示线程数,1 表示是QPS。 count:单机阈值。 strategy:流控模式。0 表示直接,1 表示关联,2 表示链路。 controlBehavior:流控效果。0 表示快速失败,1 表示Warm up,2 表示排队等待。 clusterMode:是否集群。false 表示否,true 表示是。

测试结果当应用重启后,Sentinel 控制台依旧存在之前配置的规则,规则任然有效。

三、yml 配置详解(与 Ncaos 整合)

spring:
  cloud:
    sentinel:
      datasource:
        # 名称随意
        flow:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-flow-rules
            groupId: SENTINEL_GROUP
            # 规则类型:flow(流)、degrade(降级)、param-flow(参数流)、system(系统)、authority(权限)
            # org.springframework.cloud.alibaba.sentinel.datasource.RuleType
            rule-type: flow
        degrade:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-degrade-rules
            groupId: SENTINEL_GROUP
            rule-type: degrade
        system:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-system-rules
            groupId: SENTINEL_GROUP
            rule-type: system
        authority:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-authority-rules
            groupId: SENTINEL_GROUP
            rule-type: authority
        param-flow:
          nacos:
            server-addr: localhost:8848
            dataId: ${spring.application.name}-param-flow-rules
            groupId: SENTINEL_GROUP
            rule-type: param-flow

四、json 参数详解

1、流控规则

[
  {
    // 资源名
    "resource": "/test",
    // 针对来源,若为 default 则不区分调用来源
    "limitApp": "default",
    // 限流阈值类型(1:QPS;0:并发线程数)
    "grade": 1,
    // 阈值
    "count": 1,
    // 是否是集群模式
    "clusterMode": false,
    // 流控效果(0:快速失败;1:Warm Up(预热模式);2:排队等待)
    "controlBehavior": 0,
    // 流控模式(0:直接;1:关联;2:链路)
    "strategy": 0,
    // 预热时间(秒,预热模式需要此参数)
    "warmUpPeriodSec": 10,
    // 超时时间(排队等待模式需要此参数)
    "maxQueueingTimeMs": 500,
    // 关联资源、入口资源(关联、链路模式)
    "refResource": "rrr"
  }
]

2、降级规则

[
  {
    // 资源名
    "resource": "/test1",
    "limitApp": "default",
    // 熔断策略(0:慢调用比例,1:异常比率,2:异常计数)
    "grade": 0,
    // 最大RT、比例阈值、异常数
    "count": 200,
    // 慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)
    "slowRatioThreshold": 0.2,
    // 最小请求数
    "minRequestAmount": 5,
    // 当单位统计时长(类中默认1000)
    "statIntervalMs": 1000,
    // 熔断时长
    "timeWindow": 10
  }
]

3、热点规则

[
  {
    // 资源名
    "resource": "/test1",
    // 限流模式(QPS 模式,不可更改)
    "grade": 1,
    // 参数索引
    "paramIdx": 0,
    // 单机阈值
    "count": 13,
    // 统计窗口时长
    "durationInSec": 6,
    // 是否集群 默认false
    "clusterMode": 默认false,
    // 突发事件计数
    "burstCount": 0,
    // 集群模式配置
    "clusterConfig": {
      // 失败时回退到本地
      "fallbackToLocalWhenFail": true,
      // 流程ID
      "flowId": 2,
      // 示例计数
      "sampleCount": 10,
      // 阈值类型
      "thresholdType": 0,
      // 窗口间隔时间
      "windowIntervalMs": 1000
    },
    // 流控效果(支持快速失败和匀速排队模式)
    "controlBehavior": 0,
    // 针对来源,若为 default 则不区分调用来源
    "limitApp": "default",
    // 超时时间(排队等待模式需要此参数)
    "maxQueueingTimeMs": 0,
    // 高级选项
    "paramFlowItemList": [
      {
        // 参数类型
        "classType": "int",
        // 限流阈值
        "count": 222,
        // 参数值
        "object": "2"
      }
    ]
  }
]

4、系统规则

[
  {
    // RT
    "avgRt": 1,
    // CPU 使用率
    "highestCpuUsage": -1,
    // LOAD
    "highestSystemLoad": -1,
    // 线程数
    "maxThread": -1,
    // 入口 QPS
    "qps": -1
  }
]

5、授权规则

[
  {
    // 资源名
    "resource": "sentinel_spring_web_context",
    // 流控应用
    "limitApp": "/test",
    // 授权类型(0代表白名单;1代表黑名单。)
    "strategy": 0
  }
]

五、持久化过程中碰到的错误

1、Nacos配置文件的属性名与值要和bootstrap.yml要对应上

2、Nacos配置文件中的json要注意格式正确

3、因为设置了Nacos登录,bootstrap.yml文件中但凡是涉及到Nacos下边都要设置username和password。

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

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

相关文章

子集-回溯算法

1题目 给你一个整数数组 nums &#xff0c;数组中的元素 互不相同 。返回该数组所有可能的子集&#xff08;幂集&#xff09;。 解集 不能 包含重复的子集。你可以按 任意顺序 返回解集。 示例 1&#xff1a; 输入&#xff1a;nums [1,2,3] 输出&#xff1a;[[],[1],[2],[1…

SpringBoot项目整合Redis作为缓存中间件的详细步骤

SpringBoot项目整合Redis作为缓存中间件的详细步骤 1.链接2.整合步骤3.测试Demo4.遇到的问题5.待考虑问题 有更好的建议&#xff0c;欢迎评论区留言~ 有不详细或者不准确的地方&#xff0c;欢迎评论区指正~ 有技术群嘛 hahh 可以拉我么 ~ 1.链接 哔哩教程视频 Redis官方 2.整…

线程池的工作原则揭秘:如何合理管理线程数量?

大家好&#xff0c;我是小米&#xff0c;一个热爱技术分享的小伙伴。在多线程编程中&#xff0c;线程池是一种非常实用的工具&#xff0c;可以帮助我们更好地管理线程&#xff0c;提高程序的性能和稳定性。今天&#xff0c;我将详细介绍线程池的概念、使用方法以及常用参数&…

MFC 状态栏梳理

MFC状态栏梳理 MFC状态栏&#xff0c;觉得挺简单的&#xff0c;但是用的时候总是不得劲&#xff0c;梳理了一下代码。理解通透些。 先说状态栏窗口怎么来的 在MainFrame里面会有一个成员变量&#xff0c;状态栏 m_wndStatusBar protected: // 控件条嵌入成员CMFCMenuBar …

VMware ESXi 8.0U1a 发布 - 领先的裸机 Hypervisor

VMware ESXi 8.0U1a 发布 - 领先的裸机 Hypervisor 请访问原文链接&#xff1a;https://sysin.org/blog/vmware-esxi-8-u1/&#xff0c;查看最新版。原创作品&#xff0c;转载请保留出处。 作者主页&#xff1a;sysin.org 2023-06-01, VMware vSphere 8.0U1a 发布。 详见&am…

I.MX6ULL_Linux_驱动篇(36) GPIO输入驱动

在前面我们都是使用的 GPIO 输出功能&#xff0c;还没有用过 GPIO 输入功能&#xff0c;本章我们就来学习一下在 Linux 下编写 GPIO 输入驱动程序。我们使用一个 GPIO 加输入驱动程序&#xff0c;同时利用原子操作来对按键值进行保护。 按键驱动和 LED 驱动原理上来讲基本都是…

浅谈TTF字体和Fnt字体的本质和优缺点

前言 本篇在讲什么 浅浅对TTF字体和Fnt字体的本质了解一下 本篇的特色 具有全流程的图文教学 重实践&#xff0c;轻理论&#xff0c;快速上手 提供全流程的源码内容 ★提高阅读体验★ &#x1f449; ♠ 一级标题 &#x1f448; &#x1f449; ♥ 二级标题 &#x1f448…

【Java 接口】接口(Interface)的定义,implements关键字,接口实现方法案例

博主&#xff1a;_LJaXi Or 東方幻想郷 专栏&#xff1a; Java | 从入门到入坟 专属&#xff1a;六月一日 | 儿童节 Java 接口 接口简介 &#x1f383;接口的定义 &#x1f9e7;接口实现类名定义 &#x1f381;接口实现类小案例 &#x1f388;后话 &#x1f3b0; 接口简介 &…

从架构到特性:JuiceFS 企业版首次全面解析

大多数用户是通过社区版初次接触 JuiceFS&#xff0c;企业版对大家来说可能比较陌生。与其他开源项目不同的是&#xff0c;JuiceFS 企业版比社区版更早发布&#xff0c;社区版的架构设计大量参考了企业版。对 JuiceFS 用户而言&#xff0c;这意味着社区版具有更加稳定的特性。 …

onnx模型转 ncnn 模型全连接层输出shape不对问题解决

1.简述 最近在把paddleocr 中cls分类模型通过ncnn部署框架部署时&#xff0c;发现onnx -> ncnn 模型的转换过程中出现问题。因为之前的项目都是使用ncnn框架部署的&#xff0c;只能去解决模型转换问题了。 2. 问题描述与分析 模型在onnx推理代码上正常&#xff0c;当把模型…

Fabric.js 复制粘贴元素

theme: smartblue 本文简介 点赞 关注 收藏 学会了 当你要复制一个 fabric 的元素时&#xff0c;你考虑到的是什么&#xff1f;是深拷贝当前选中对象再添加到画布中&#xff1f; 其实&#xff0c;fabric.js 提供了一个克隆方法&#xff0c;在 fabric.js 官网的案例里也有这个…

自动驾驶赛道回暖?传统Tier1加速入场,真正赢家正在浮出水面

自动驾驶赛道&#xff0c;在经历过去三年的持续降温之后&#xff0c;正在迎来新一轮上升势头。整合、并购、协作&#xff0c;正在成为新一轮产业周期的关键词。 本周&#xff0c;滴滴自动驾驶与法雷奥签署战略合作及投资意向书&#xff0c;法雷奥将对滴滴自动驾驶进行战略投资…

【VMware】局域网里机器A访问机器B内部的vm虚拟机

一、机器B配置 1、打开机器B上面的VMware&#xff0c;在菜单里找到编辑&#xff0c;在编辑里找到“虚拟网络编辑器” 2、选择 net 项&#xff0c;点击NET设置 3、填写主机端口8090&#xff0c;主机端口不要和其它端口冲突就行&#xff0c;这个端口后面会在机器A上面用到 3.1、…

111.(cesium篇)cesium地球自转

听老人家说:多看美女会长寿 地图之家总目录(订阅之前建议先查看该博客) 文章末尾处提供保证可运行完整代码包,运行如有问题,可“私信”博主。 效果如下所示: 下面献上完整代码,代码重要位置会做相应解释 <html lang="en">

电脑病毒怎么彻底清理?这3个方法可以解决!

案例&#xff1a;电脑中毒无法正常使用怎么办&#xff1f;怎么清理电脑病毒&#xff1f;如何彻底清除病毒&#xff1f;有没有小伙伴知道解决的方法&#xff1f; 在使用电脑的过程中&#xff0c;我们经常会遇到电脑中病毒的情况&#xff0c;它们能够通过各种渠道感染你的计算机…

搭建服务器环境

如果是刚安装好的操作系统 先安装源里的gcc cmake make 等 apt-get install gcc g make cmake autoconf automake libtool 1.gcc 4.8.2 (1)上传gcc 源码在source/下 把gcc-4.8.2.tar.gz放在/home/download/ cd /home/download/ tar -xzvf gcc-4.8.2.tar.gz cd gcc-4.8.2 (2)安…

[POJO]POJO的设计规范Lombok框架

POJO的设计规范 所有用于声明属性的类&#xff0c;都应该遵循以下规范&#xff1a; 存在无参数构造方法 所有属性都是私有权限&#xff08;private&#xff09;的 添加每个属性对应的Setters & Getters 添加基于所有属性的hashCode()与equals() 必须保证&#xff1a;如…

unity | 动画模块之滚动选项框

一、效果动画 如果不是你们想要的&#xff0c;就省的你们继续往下看了 二、作者的话 对于我来说&#xff0c;计算一大堆数据简直太难了&#xff0c;所以自己想了点方法 三、基本功的要求 需要会使用Scroll View 四、进入正题 1.先做一个scrollView把自己想做的东西放进去…

Ubuntu22.04 VirtualBox

Ubuntu22.04 VirtualBox 通常三种虚拟机网络连入模式 桥接网卡 虚拟网卡连入宿主机所在的路由器&#xff0c;公用一个网关地址&#xff0c;自动分配路由器ip到虚拟网卡上&#xff0c;相当于和物理机一样的地址&#xff0c;在同一网段&#xff0c;其他物理机和这个虚拟机一样…

作为一个前端Leader,当你接到一个项目时,应该如何初始化您的项目

1、分析需求 拿到需求后&#xff0c;不是立马动工&#xff0c;我们需要先了解项目的业务需求和用户需求&#xff0c;并明确项目的范围&#xff0c;包括功能点、时间和预算等&#xff0c;来确定项目需求和范围。 2、技术栈选择 根据项目的需求和范围以及团队成员的技术栈&…