SpringCloud(22)之Sentinel实战应用

一、Sentinel核心库

        sentinel主页:主页 · alibaba/Sentinel Wiki · GitHub

1.1 Sentinel介绍 

         随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。

1)Sentinel核心组件

1:核心库(Java 客户端 不依赖任何框架/库,能够运行于 Java 7 及以上的版本的运行时环境,同 时对 Dubbo / Spring Cloud 等框架也有较好的支持。

2:控制台(Dashboard):控制台主要负责管理推送规则、监控、集群限流分配管理、机器发现等。

2)Sentinel VS Hystrix 

对比内容

Sentinel

Hystrix

隔离策略

信号量隔离

线程池隔离/信号量隔离

熔断降级策略

基于响应时间或失败比率

基于失败比率

实时指标实现

滑动窗口

滑动窗口(基于 RxJava

规则配置

支持多种数据源

支持多种数据源

扩展性

多个扩展点

插件的形式

基于注解的支 持

支持

支持

限流

基于 QPS,支持基于调用关系的限流

不支持

流量整形

支持慢启动、匀速器模式

不支持

系统负载保护

支持

不支持

控制台

开箱即用,可配置规则、查看秒级监控、机器 发现等

不完善

常见框架的适 配

ServletSpring Cloud DubbogRPC 

ServletSpring Cloud

Netflix

3)Sentinel概念 

  • 资源:资源是Sentinel的关键概念,他可以是Java应用程序的任何内容,例如,由应用程序提供的服务,或由应用程序调用其他服务提供的服务,甚至可以是一段代码; 只要通过Sentinel API定义的代码,就是资源,能够被Sentinel保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源来标示资源。
  • 规则:围绕资源的实时状态设定的规则,可以包括流量控制规则,熔断规则以及系统保护规则,所有规则可以动态实时调整。

1.2 Sentinel核心功能

 1.2.1 流量控制

        流量控制在网络传输中是一个常用的概念,他用于调整网络包的发送数据,然而,从系统的稳定性角度考虑,也有非常多的讲究。在任意时刻到来的请求往往是随机不可控的,而系统的处理能力有限,我们需要根据系统的的处理能力对流量进行控制.Sentinel作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:

流量控制设计理念 

流量控制有以下几个角度:

  • 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
  • 运行指标,例如:QPS、线程池、系统负载等;
  • 控制的效果,例如直接限流、冷启动、排队等;

        Sentinel 的设计理念是让您自由选择控制的角度,并进行灵活组合,从而达到想要的效果。

1.2.2 熔断降级

        除了流量控制之外,及时对调用链路中的不稳定因素进行熔断也是Sentinel的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,可能会导致请求堆积,进而导致级联故障。

 

        Sentinel 和 Hystrix 的原则是一致的: 当检测到调用链路中某个资源出现不稳定的表现,例如请求响应时间长或异常比例升高的时候,则对这个资源的调用进行限制,让请求快速失败,避免影响到其它的资源而导致级联故障。

 1)Sentinel熔断设计理念

        Hystrix通过线程池隔离的方式,来对依赖进行了隔离,这样做的好处就是资源和资源之间 做到了最彻底的隔离。缺点就是增加了线程切换的成本,还要先给各个资源做线程池大小的分配。

        Sentinel对这个问题采取了两种手段:

  • 通过并发线程数进行控制

        和资源池隔离的方法不同,Sentinel通过限制资源并发线程的数量,来减少不稳定资源对其他资源的影响。也不需要预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间过长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源商堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才会开始继续处理请求。

  • 通过响应时间对资源进行降级

        除了对并发线程数进行控制外,Sentinel还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会直接被拒绝,直到过了指定时间的窗口后才恢复。

2)系统自适应保护

        Sentinel同时提供系统维度的自适应能力。防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统奔溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其他机器上,如果这个时候其他的机器也处于一个边缘状态,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。

        针对这个情况,Sentinel提供了对应的保护机制,让系统的入口流量和系统负载达到一个平衡,保证系统在能力范围之内处理最多的请求。

1.3 Sentinel熔断限流

         Sentinel可以简单的分为Sentinel核心库和Dashboard。核心库不依赖Dashboard,但是结合Dashboard可以取得最后的效果。我们先来学习一下Sentinel核心库的使用。后面在学习Dashboard的使用。

        在我们项目中,用户请求通过 hailtaxi-gateway路由到 hailtaxi-driver 或者 hailtaxi-order ,还 有可能在 hailtaxi-order 中使用feign调用 hailtaxi-driver ,所以我们有可能在单个服务中实现熔   断限流,也有可能要集成feign调用实现熔断限流,还有可能在微服务网关中实现熔断限流。我们接下   来一步一步实现每一种熔断限流操作。 

1.3.1 Springboot集成

        如果在Springboot项目中集成,首先需要引入依赖,并使用@SentinelResource标记资源。

 1.3.1.1 @SentinelResource注解

         @SentinelResource 用于定义资源,并提供可选的异常处理和 fallback 配置项。

        @SentinelResource 注解包含以下属性:

value

资源名称,必需项(不能为空)

blockHandler /

blockHandlerClass

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

blockHandlerClass 为对应的类的 Class 对象,注意对应的函数必 需为 static 函数,否则无法解析。

fallback / fallbackClass

fallback 函数名称,可选项,用于在抛出异常的时候提供 fallback

处理逻辑。fallback 函数可以针对所有类型的异常(除了

exceptionsToIgnore 里面排除掉的异常类型)进行处理。  fallback 函数签名和位置要求:  返回值类型必须与原函数返回值类型一

致; 方法参数列表需要和原函数一致,或者可以额外多一个

Throwable 类型的参数用于接收对应的异常。   fallback 函数默认 需要和原方法在同一个类中。若希望使用其他类的函数,则可以指  fallbackClass 为对应的类的 Class 对象,注意对应的函数必需    static 函数,否则无法解析。

defaultFallback(1.6.0  )

默认的 fallback 函数名称,可选项,通常用于通用的 fallback 逻辑 (即可以用于很多服务或方法)。默认 fallback 函数可以针对所有类   型的异常(除了 exceptionsToIgnore 里面排除掉的异常类型)进行处 理。若同时配置了 fallback defaultFallback,则只有 fallback     会生效。  defaultFallback 函数签名要求:  返回值类型必须与原   函数返回值类型一致; 方法参数列表需要为空,或者可以额外多 一个 Throwable 类型的参数用于接收对应的异常。   

defaultFallback 函数默认需要和原方法在同一个类中。若希望使用 其他类的函数,则可以指定 fallbackClass 为对应的类的 Class 

象,注意对应的函数必需为 static 函数,否则无法解析。

exceptionsToIgnore(1.6.0 开始)

用于指定哪些异常被排除掉,不会计入异常统计中,也不会进入 fallback 逻辑中,而是会原样抛出。

entryType

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

1.3.1.2 blockHandler

        在对应的模块中加入依赖:

        <!--sentinel--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId><version>2.2.5.RELEASE</version></dependency>

        我们为 info()方法添加一个 @SentinelResource注解,用来标注资源,表示当前方法需要执行限流、降级,在注解中添加value属性,用来标注资源,说白了就是给当前资源起个名字,blockHandler  用来表示当前方法发生 BlockException异常的时候,将处理流程交给指定的方法 blockExHandler() 处理,此时 blockExHandler()方法必须和抛出异常的方法在同一个类中,这是一种降级操作,代码如   下:

    @SentinelResource(value = "info",blockHandler = "blockExHandler")public Driver info(@PathVariable(value = "id")String id) throws InterruptedException{Driver driver = driverService.findById(id);//if(id.equals("1")){//    TimeUnit.SECONDS.sleep(10);//}if(driver==null){//throw new RuntimeException("司机不存在");throw new SystemBlockException("info","hailtaxi-driver");//必须抛出BlockException才会生效}driver.setName(driver.getName()+",IP="+ip);return driver;}/**** BlockException异常处理*/public Driver blockExHandler(String id,BlockException ex){Driver driver = new Driver();driver.setId(id);driver.setName("bbb");return driver;}

        如果访问一个没有的数据就会报错异常,此时就会走blockhandler里面的逻辑。

1.3.1.3 fallback使用 

         如果我们希望抛出任何异常都能处理,都能调用默认处理方法,而并非只是 BlockException异常才调 用,此时可以使用 @SentinelResource  fallback属性,代码如下:

    @SentinelResource(value = "info",fallback ="exHandler")public Driver info(@PathVariable(value = "id")String id) throws InterruptedException{Driver driver = driverService.findById(id);//if(id.equals("1")){//    TimeUnit.SECONDS.sleep(10);//}if(driver==null){throw new RuntimeException("司机不存在");
//            throw new SystemBlockException("info","hailtaxi-driver");//必须抛出BlockException才会生效}driver.setName(driver.getName()+",IP="+ip);return driver;}/**** 异常处理*/public Driver exHandler(String id){Driver driver = new Driver();driver.setId(id);driver.setName("aaa");return driver;}

         访问 http://localhost:18081/driver/info/3 测试出错效果如下:

        如果我们处理异常逻辑跟原方法不在同一个类中,可以使用@SentinelResource注解的fallbackclass实现,代码如下:

@SentinelResource(value = "info",fallback ="exHandler" ,fallbackClass ="xx.xxx.xxx.xx.Xxx")
 1.3.1.4 defaultFallback

         上面无论是 blockHandler还是 fallback ,每个方法发生异常,都要为方法独立创建一个处理异常的   方法,效率非常低,我们可以使用 @SentinelResource注解的 defaultFallback属性,为一个类指定 一个全局的处理错误的方法,代码如下:

@RestController
@RequestMapping(value = "/driver")
@RefreshScope
@SentinelResource(defaultFallback ="defaultExFallback")
public class DriverController {/**** 异常处理*/public Driver defaultExFallback() {Driver driver = new Driver();driver.setName("系统繁忙,请稍后再试!");return driver;}
}

         此时需要注意,  defaultFallback属性指定的方法入参必须为空,最多可以增加一个异常对象。我们访问 http://localhost:18081/driver/info/3 效果如下:

1.3.2 限流规则 

         Sentinel支持多种限流规则,规则我们可以在代码中直接定义,规则属性如下:

Field

说明

默认值

resource

资源名,资源名是限流规则的作用对象

count

限流阈值

grade

限流阈值类型,QPS 模式(1)或并发线程数模式  0

QPS 模式

limitApp

流控针对的调用来源

default ,代表不区 分调用来源

strategy

调用关系限流策略:直接、链路、关联

根据资源本身(直

接)

controlBehavior

流控效果(直接拒绝/WarmUp/匀速+排队等 ),不支持按调用关系限流

直接拒绝

clusterMode

是否集群限流

1.3.2.1 流量控制 

         理解上面规则的定义之后,我们可以通过调用  FlowRuleManager.loadRules() 方法来用硬编码的方 式定义流量控制规则。

1)QPS流量控制

         我们先实现流量基于QPS控制,在 hailtaxi-driver  DriverApplication启动类上添加如下方法加 载限流规则,当 DriverApplication初始化完成之后加载规则,代码如下:

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.xxxxx.driver.mapper")
@EnableAutoDataSourceProxy
public class DriverApplication {public static void main(String[] args) throws InterruptedException {ApplicationContext applicationContext = SpringApplication.run(DriverApplication.class,args);}/**** 初始化规则*/@PostConstructprivate void initFlowQpsRule() {//规则集合List<FlowRule> rules = new ArrayList<FlowRule>();//定义一个规则FlowRule rule = new FlowRule("info");// 设置阈值rule.setCount(2);//设置限流阈值类型rule.setGrade(RuleConstant.FLOW_GRADE_QPS);//QPS控制
//        rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);//线程数控制//default,代表不区分调用来源rule.setLimitApp("default");//将定义的规则添加到集合中rules.add(rule);//加载规则FlowRuleManager.loadRules(rules);}
}

        我们访问 http://localhost:18081/driver/info/1此时不会抛出异常,但是频繁刷新,则会调用降 级方法,效果如下: 

2)线程数流量控制 

         我们修改限流阈值类型,代码如下:

@SpringBootApplication
@EnableDiscoveryClient
@MapperScan(basePackages = "com.xxxxx.driver.mapper")
@EnableAutoDataSourceProxy
public class DriverApplication {public static void main(String[] args) throws InterruptedException {ApplicationContext applicationContext = SpringApplication.run(DriverApplication.class,args);}/**** 初始化规则*/@PostConstructprivate void initFlowQpsRule() {//规则集合List<FlowRule> rules = new ArrayList<FlowRule>();//定义一个规则FlowRule rule = new FlowRule("info");// 设置阈值rule.setCount(2);//设置限流阈值类型rule.setGrade(RuleConstant.FLOW_GRADE_THREAD);//线程数控制//default,代表不区分调用来源rule.setLimitApp("default");//将定义的规则添加到集合中rules.add(rule);//加载规则FlowRuleManager.loadRules(rules);}
}

         此时再来访问 http://localhost:18081/driver/info/1我们发现用浏览器无论怎么访问都不会出现 降级现象,但是如果用Jmeter模拟多个线程,效果就不一样了,效果如下:

 1.3.2.2 熔断降级

         熔断降级规则包含下面几个重要的属性:

Field

说明

默认

resource

资源名,即规则的作用对象

grade

熔断策略,支持慢调用比例/异常比例/异常数策略

慢调

用比

count

慢调用比例模式下为慢调用临界 RT(超出该值计为慢调 );异常比例/异常数模式下为对应的阈值

timeWindow

熔断时长,单位为 s

minRequestAmount

熔断触发的最小请求数,请求数小于该值时即使异常比率超出 阈值也不会熔断(1.7.0 引入)

5

statIntervalMs

统计时长(单位为 ms ), 60*1000 代表分钟级(1.8.0  入)

1000

ms

slowRatioThreshold

慢调用比例阈值,仅慢调用比例模式有效(1.8.0 引入)

         同一个资源可以同时有多个降级规则。理解上面规则的定义之后,我们可以通过调用 DegradeRuleManager.loadRules() 方法来用硬编码的方式定义流量控制规则,在  DriverApplication 规则定义如下:

    /**** 熔断降级规则*/@PostConstructprivate void initDegradeRule() {//降级规则集合List<DegradeRule> rules = new ArrayList<DegradeRule>();//降级规则对象DegradeRule rule = new DegradeRule();//设置资源rule.setResource("info");//设置触发降级阈值rule.setCount(2);/*** 熔断降级策略,支持慢调用比例/异常比例/异常数策略* DEGRADE_GRADE_RT:平均响应时间* DEGRADE_GRADE_EXCEPTION_RATIO:异常比例数量* DEGRADE_GRADE_EXCEPTION_COUNT:异常数*/rule.setGrade(RuleConstant.DEGRADE_GRADE_EXCEPTION_COUNT);//熔断窗口时长,单位为 srule.setTimeWindow(10);//将规则添加到集合中rules.add(rule);//加载规则DegradeRuleManager.loadRules(rules);}
 1.3.2.3 系统自我保护

         Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 LoadCPU 使用率、总体 平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量 和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。

        系统规则包含下面几个重要的属性:

Field

说明

默认值

highestSystemLoad

load1 触发值,用于触发自适应控制阶段

-1 (不生效)

avgRt

所有入口流量的平均响应时间

-1 (不生效)

maxThread

入口流量的最大并发数

-1 (不生效)

qps

所有入口资源的 QPS

-1 (不生效)

highestCpuUsage

当前系统的 CPU 使用率(0.0-1.0

-1 (不生效)

         理解上面规则的定义之后,我们可以通过调用 SystemRuleManager.loadRules() 方法来用硬编码的 方式定义流量控制规则。

    /**** 系统自我保护*///@PostConstructprivate void initSystemRule() {//系统自我保护集合List<SystemRule> rules = new ArrayList<>();//创建系统自我保护规则SystemRule rule = new SystemRule();//CPU使用率 值为0-1,-1 (不生效)rule.setHighestCpuUsage(0.2);//所有入口资源的 QPS,-1 (不生效)rule.setQps(10);//入口流量的最大并发数,-1 (不生效)rule.setMaxThread(5);//所有入口流量的平均响应时间,单位:秒,-1 (不生效)rule.setAvgRt(5);//load1 触发值,用于触发自适应控制阶段,系统最高负载,建议取值 CPU cores * 2.5rule.setHighestSystemLoad(20);//将规则加入到集合rules.add(rule);SystemRuleManager.loadRules(rules);}
1.3.2.4 热点数据 

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

1:商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制

2:用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制

         热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调 用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效.

         Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控。热点 参数限流支持集群模式。

        要使用热点参数限流功能,需要引入以下依赖:

        <!--热点参数--><dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-parameter-flow-control</artifactId><version>1.8.1</version></dependency>

        然后为对应的资源配置热点参数限流规则,并在 entry  的时候传入相应的参数,即可使热点参数限流 生效。

         热点参数规则(  ParamFlowRule  )类似于流量控制规则(  FlowRule ):

属性

说明

默认值

resource

资源名,必填

count

限流阈值,必填

grade

限流模式

QPS  

durationInSec

统计窗口时间长度(单位为秒),1.6.0 版本开始支持

1s

controlBehavior

流控效果(支持快速失败和匀速排队模式),1.6.0 版本开 始支持

快速失

maxQueueingTimeMs

最大排队等待时长(仅在匀速排队模式生效),1.6.0 版本 开始支持

0ms

paramIdx

热点参数的索引,必填,对应 SphU.entry(xxx, args) 中的参数索引位置

paramFlowItemList

参数例外项,可以针对指定的参数值单独设置限流阈值, 不受前面 count 阈值的限制。  仅支持基本类型和字符串  类型

         我们可以对热门参数比如下标为0的参数流量进行控制,对热点数据执行特殊限流,比如参数值为 tj  时候执行限流,在 DriverApplication 中创建限流配置,代码如下:

    /**** 热点参数初始化*/@PostConstructprivate static void initParamFlowRules() {ParamFlowRule rule = new ParamFlowRule("search")//参数下标为0.setParamIdx(0)//限流模式为QPS.setGrade(RuleConstant.FLOW_GRADE_QPS)//统计窗口时间长度(单位为秒).setDurationInSec(10)/*** 流控效果(支持快速失败和匀速排队模式)* CONTROL_BEHAVIOR_DEFAULT:限流行为,直接拒绝* CONTROL_BEHAVIOR_WARM_UP:限流行为,匀速排队 冷启动* CONTROL_BEHAVIOR_RATE_LIMITER:限流行为,匀速排队*/.setControlBehavior(RuleConstant.CONTROL_BEHAVIOR_DEFAULT)//最大排队等待时长(仅在匀速排队模式生效  CONTROL_BEHAVIOR_RATE_LIMITER)//.setMaxQueueingTimeMs(600)//最大阈值为5.setCount(5);// 为特定参数单独设置阈值.//如下配置:当下标为0的参数值为tj的时候,阈值到达2的时候则执行限流ParamFlowItem item = new ParamFlowItem()//参数类型为int类型.setClassType(String.class.getName())//设置阈值为2.setCount(2)//需要统计的值.setObject(String.valueOf("tj"));rule.setParamFlowItemList(Collections.singletonList(item));//加载热点数据ParamFlowRuleManager.loadRules(Collections.singletonList(rule));}

1.3  Sentinel对OpenFeign支持 

         Sentinel 适配了 Feign 组件。如果想使用,除了引入  spring-cloud-starter-alibaba-sentinel 的依 赖外还需要 2 个步骤:

1:配置文件打开 Sentinel  Feign 的支持:feign.sentinel.enabled=true

2:加入 spring-cloud-starter-openfeign 依赖使 Sentinel starter 中的自动化配置类生效

1)引入依赖 

        <!--sentinel--><dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId> <version>2.2.5.RELEASE</version></dependency><!--Openfeign--><dependency><groupId>org.springframework.cloud</groupId><artifactId>spring-cloud-starter-openfeign</artifactId></dependency>

 2)还需要在Feign调用客户端中开启Feign的支持

feign:compression:request:enabled: true # 开启请求压缩mime-types: text/html,application/xml,application/json # 设置压缩的数据类型min-request-size: 2048 # 设置触发压缩的大小下限#以上数据类型,压缩大小下限均为默认值response:enabled: true # 开启响应压缩#开启Sentinel对Feign的支持sentinel:enabled: true

 1.3.1 fallback

         我们可以为Feign接口创建一个实现类,在实现类中处理程序异常降级处理方法,代码如下:

@Component
public class DriverFeignFallback implements DriverFeign {/*** status()降级处理方法*/@Overridepublic Driver status(String id, Integer status) {Driver driver = new Driver();driver.setId(id);driver.setStatus(status);driver.setName("系统比较繁忙,请您稍后再试!");return driver;}
}

         我们还需要在Feign接口上添加 fallback属性指定讲解处理的类,代码如下:

@FeignClient(value = "hailtaxi-driver",fallback = DriverFeignFallback.class)

1.3.2 fallbackFactory 

        我们可以为Feign接口创建一个降级处理的工厂对象,在工厂对象中处理程序异常降级处理方法,代码 如下:

@Component
public class DriverFeignFallbackFactory implements FallbackFactory<DriverFeign> {@Overridepublic DriverFeign create(Throwable throwable) {return new DriverFeign() {/*** status()降级处理方法*/@Overridepublic Driver status(String id, Integer status) {Driver driver = new Driver();driver.setId(id);driver.setStatus(status);driver.setName("系统比较繁忙,请您稍后再试!");return driver;}};}
}

         我们还需要在Feign接口上添加 fallbackFactory属性指定讲解处理的类,代码如下:

@FeignClient(value = "hailtaxi-driver",fallbackFactory =
DriverFeignFallbackFactory.class)

         此时我们测试,效果如下:

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C# wpf 使用GDI实现截屏

wpf截屏系列 第一章 使用GDI实现截屏&#xff08;本章&#xff09; 第二章 使用GDI实现截屏 第三章 使用DockPanel制作截屏框 第四章 实现截屏框热键截屏 第五章 实现截屏框实时截屏 第六章 使用ffmpeg命令行实现录屏 文章目录 wpf截屏系列前言一、导入gdi32方法一、NuGet获取…

88. 合并两个有序数组 (Swift版本)

题目 给你两个按 非递减顺序 排列的整数数组 nums1 和 nums2&#xff0c;另有两个整数 m 和 n &#xff0c;分别表示 nums1 和 nums2 中的元素数目。 请你 合并 nums2 到 nums1 中&#xff0c;使合并后的数组同样按 非递减顺序 排列。 注意&#xff1a;最终&#xff0c;合并…

Python数据分析-5

1.时间序列 2.pandas重采样 重采样&#xff1a;指的是将时间序列从一个频率转化为另一个频率进行处理的过程&#xff0c;将高频率数据转化为低频率数据为降采样&#xff0c;低频率转 化为高频率为升采样。 统计出911数据中不同月份电话次数的变化情况&#xff1a…

PlantUML Integration 编写短信服务类图

PlantUML Integration 写一个类图&#xff0c;主要功能为 1、编写一个serviceSms短信服务类&#xff1b; 2、需要用到短信的地方统一调用基建层的服务即可&#xff1b; 3、可以随意切换、增加短信厂商&#xff0c;不需要更改场景代码&#xff0c;只需要更改application.yml 里面…

边缘计算与物联网的核心 —— 低功耗芯片

一、低功耗芯片 在边缘计算与物联网&#xff08;IoT&#xff09;中&#xff0c;低功耗芯片扮演了至关重要的角色&#xff0c;主要体现在以下几个方面&#xff1a; 延长设备寿命&#xff1a;物联网设备通常需要部署在难以更换电池或不方便进行频繁维护的环境中&#xff0c;比如…

学习使用postman软件上传文件发起api接口请求

学习使用postman软件上传文件发起api接口请求 设置headers头信息设置body 设置headers头信息 如图设置&#xff1a; KEY&#xff1a;Content-Type VALUE&#xff1a;multipart/form-data 设置body 设置需要上传的key对应的类型为File&#xff0c;上传类型 设置需要上传的文件…

物联网技术助力智慧城市转型升级:智能、高效、可持续

目录 一、物联网技术概述及其在智慧城市中的应用 二、物联网技术助力智慧城市转型升级的路径 1、提升城市基础设施智能化水平 2、推动公共服务智能化升级 3、促进城市治理现代化 三、物联网技术助力智慧城市转型升级的成效与展望 1、成效显著 2、展望未来 四、物联网技…

import gdal 报错

1.下载gdal https://www.lfd.uci.edu/~gohlke/pythonlibs/#gdal 2.安装正确版本 &#xff08;1&#xff09;查看python版本 python -v我的版本Python 3.7.9 建议下载 GDAL-3.4.2-cp37-cp37m-win_amd64.whl &#xff08;2&#xff09;放到Scripts文件夹下 执行 pip install GD…

CVPR2024 | 大核卷积新高度101x101,美团提出PeLK

https://arxiv.org/pdf/2403.07589.pdf 本文概述 最近&#xff0c;一些大核卷积网络以吸引人的性能和效率进行了反击。然而&#xff0c;考虑到卷积的平方复杂度&#xff0c;扩大内核会带来大量的参数&#xff0c;而大量的参数会引发严重的优化问题。由于这些问题&#xff0c;当…

网络编程套接字(4)——Java套接字(TCP协议)

目录 一、Java流套接字通信模型 二、TCP流套接字编程 1、ServerSocket ServerSocket构造方法&#xff1a; ServerSocket方法: 2、Socket Socket构造方法&#xff1a; Socket方法&#xff1a; 三、代码示例&#xff1a;回显服务器 1、服务器代码 代码解析 2、客户端…

机械女生,双非本985硕,目前学了C 基础知识,转嵌入式还是java更好?

作为单片机项目开发的卖课佬&#xff0c;个人建议&#xff0c;先转嵌入式单片机开发方向&#xff0c;哈哈。 java我也学过&#xff0c;还学过oracle、mysql数据库&#xff0c;只是当时没做笔记&#xff0c;找不好充分的装逼证据了。 从实习通过业余时间&#xff0c;学到快正式毕…

AI 大模型赋能手机影像,小米14 Ultra 让真实有层次

2月22日&#xff0c;小米龙年第一场重磅发布会&#xff0c;正式发布专业影像旗舰小米14 Ultra。 此前小米发布的两代 Ultra&#xff0c;在不同维度&#xff0c;引领了移动影像行业的走向。最新的小米14 Ultra 在定义的时候&#xff0c;我们反复在思考&#xff1a;怎么才能把移动…

HBase安装,配置,启动,检查

目录: 一、HBase安装&#xff0c;配置 1、下载HBase安装包 2、解压&#xff0c;配置环境变量并激活 3、hbase 配置 4、将hadoop和zookeeper的配置文件创建软连接放在hbase配置目录 5、配置 regionserver 和 backup-master 二、HBase启动与关闭&#xff0c;安装检验 1、启动关闭…

吴恩达深度学习笔记:神经网络的编程基础2.9-2.14

目录 第一门课&#xff1a;神经网络和深度学习 (Neural Networks and Deep Learning)第二周&#xff1a;神经网络的编程基础 (Basics of Neural Network programming)2.9 逻辑回归中的梯度下降&#xff08;Logistic Regression Gradient Descent&#xff09; 第一门课&#xff…

蓝牙耳机链接电脑莫名奇妙关机问题(QQ浏览器)

蓝牙耳机连接电脑听歌的时候&#xff0c;如果听歌软件是暴风影音&#xff0c;或者其它播放器&#xff0c;蓝牙不会自动关机&#xff0c;但如果是QQ浏览器&#xff0c;蓝牙耳机经常莫名其妙的关机&#xff0c;时间间隔忽长忽短&#xff0c;没有规律&#xff0c;解决办法就是重启…

【C++ 设计模式】简单工厂模式

文章目录 前言一、简单工厂模式是什么&#xff1f;二、实现原理三、UML类图四、简单工厂模式具体代码总结 前言 在软件开发中&#xff0c;设计模式是解决特定问题的可复用解决方案。其中&#xff0c;简单工厂模式是一种创建型设计模式&#xff0c;旨在封装对象的创建过程&…

使用耳机壳UV树脂制作私模定制耳塞的价格如何呢?

耳机壳UV树脂制作私模定制耳塞的价格因多个因素而异&#xff0c;如材料、工艺、设计、定制复杂度等。 根据我目前所了解到的信息&#xff0c;使用UV树脂制作私模定制耳塞的价格可能在数百元至数千元不等。具体价格还需根据用户的需求和预算进行综合考虑。 如需获取更准确的报…

MySQL order by 语句执行流程

全字段排序 假设这个表的部分定义是这样的&#xff1a; CREATE TABLE t (id int(11) NOT NULL,city varchar(16) NOT NULL,name varchar(16) NOT NULL,age int(11) NOT NULL,addr varchar(128) DEFAULT NULL,PRIMARY KEY (id),KEY city (city) ) ENGINEInnoDB; 有如下 SQL 语…

抖音在线点赞任务发布接单运营平台PHP网站源码

源码简介 抖音在线点赞任务发布接单运营平台PHP网站源码 多个支付通道分级会员制度 介绍&#xff1a; 1、三级代理裂变&#xff0c;静态返佣/动态返佣均可设置。&#xff08;烧伤制度&#xff09;。 2、邀请二维码接入防红跳转。 3、自动机器人做任务&#xff0c;任务时间…

STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹

STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹 文章目录 STM32CubeIDE基础学习-STM32CubeIDE软件新增工程文件夹前言第1章 添加文件夹第2章 添加文件路径2.1 相对路径方法2.2 绝对路径方法 总结 前言 在编程的过程中&#xff0c;如果需要在原有的工程基础上新增其它的…