【分布式微服务专题】从单体到分布式(四、SpringCloud整合Sentinel)
目录
- 前言
- 阅读对象
- 阅读导航
- 前置知识
- 一、什么是服务雪崩
- 1.1 基本介绍
- 1.2 解决方案
- 二、什么是Sentinel
- 2.1 基本介绍
- 2.2 设计目的
- 2.3 基本概念
- 三、Sentinel 功能和设计理念
- 3.1 流量控制
- 3.2 熔断降级
- 3.3 系统负载保护
- 四、Sentinel 是如何工作的
- 笔记正文
- 一、简单整合Sentinel
- 1.1 添加maven依赖
- 1.2 接入限流埋点:定义Sentinel资源
- 1.3 配置限流规则:定义Sentinel规则
- 1.4 设置熔断规则
- 1.4.1 Dubbo整合Sentinel
- 1.5 设置系统负载保护
- 二、概念补充:Sentinel规则
- 2.1 规则的种类
- 2.1.1 流量控制规则 (FlowRule)
- 2.1.2 熔断降级规则 (DegradeRule)
- 2.1.3 系统保护规则 (SystemRule)
- 2.1.4 访问控制规则 (AuthorityRule)
- 2.1.5 热点规则 (ParamFlowRule)
- 学习总结
- 感谢
前言
相对来说,Sentinel的学习难度比之之前的Dubbo要低了不少。不过在学习过程中也遇到了一些认知局限带来的困难。比如,虽然还是学习了Sentinel,但是不知道生产环境该如何配置才是最佳的状态。
说到底,Sentinel还是没有提供很好的文档支持。比如:生产最佳实践方案。 官方也确实提供了一个,但是总感觉不太完备。
另外在学习的过程中再次提醒了我:不要盲目的添加中间件,中间件的引入势必会造成系统复杂度上升,也带来了一定的运维成本。所以,若非有必要的,还是不要特定地去引入某个中间件吧。
最难受的是,文档资料的缺失,不少问题官网没解释,百度没答案,难受死了。
当然,这里是以学习目的出发的,就算是引入也无所谓。
阅读对象
阅读导航
系列上一篇文章:《【分布式微服务专题】从单体到分布式(三、SpringCloud整合Dubbo)》
前置知识
一、什么是服务雪崩
1.1 基本介绍
在一个高度服务化的系统中,我们实现的一个业务逻辑通常会依赖多个服务。比如:订单服务会依赖用户服务、商品服务等。此时,若其中一个服务不可用,就会导致订单服务的所有线程都因等待而引起阻塞,最终导致没有线程可用,进而引起整个服务不可用,这就是服务雪崩
导致服务不可用的可能有很多,比如:程序BUG、流量激增、缓存击穿,甚至是硬件故障。
在服务提供者不可用的时候,会出现大量重试的情况:用户重试、代码逻辑重试,这些重试最终导致进一步的流量激增,所以归根结底导致雪崩效应的最根本原因是:大量请求线程同步等待造成的资源耗尽。当服务调用者使用同步调用时, 会产生大量的等待线程占用系统资源。一旦线程资源被耗尽,服务调用者提供的服务也将处于不可用状态,于是服务雪崩效应产生了
1.2 解决方案
服务雪崩常用的解决方案如下:
- 超时机制:设定接口超时时间,不做无休止的等待。属于一种缓解手段,只要流量足够大,依然有击穿的可能性
- 服务限流:限制QPS,避免流量突增而故障。属于一种预防手段
- 服务熔断降级:类似保险丝。如果某个服务调用慢,或者本身短时间内就有大量超时,那后续的请求再进来其实已经没有意义了,不如快速返回一个失败答复,避免拥挤(参考以前你抢小米手机的时候)
二、什么是Sentinel
Sentinel官方文档传送门:传送门
2.1 基本介绍
随着微服务的流行,服务和服务之间的稳定性变得越来越重要。Sentinel 是面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
2.2 设计目的
流量
流量
流量
面向分布式、多语言异构化服务架构的流量治理组件,主要以流量为切入点,从流量路由、流量控制、流量整形、熔断降级、系统自适应过载保护、热点流量防护等多个维度来帮助开发者保障微服务的稳定性。
2.3 基本概念
资源
资源是 Sentinel 的关键概念。它可以是 Java 应用程序中的任何内容,例如,由应用程序提供的服务,或由应用程序调用的其它应用提供的服务,甚至可以是一段代码。在接下来的文档中,我们都会用资源来描述代码块。
意思是,粒度可以为:进程、组件、方法,甚至是一段代码
只要通过 Sentinel API 定义的代码,就是资源,能够被 Sentinel 保护起来。大部分情况下,可以使用方法签名,URL,甚至服务名称作为资源名来标示资源。
规则
围绕资源的实时状态设定的规则,可以包括流量控制规则、熔断降级规则以及系统保护规则。所有规则可以动态实时调整。
三、Sentinel 功能和设计理念
Sentinel主要的功能有:流量控制、熔断降级、系统负载保护
3.1 流量控制
流量控制在网络传输中是一个常用的概念,它用于调整网络包的发送数据。然而,从系统稳定性角度考虑,在处理请求的速度上,也有非常多的讲究。任意时间到来的请求往往是随机不可控的,而系统的处理能力是有限的。我们需要根据系统的处理能力对流量进行控制。Sentinel 作为一个调配器,可以根据需要把随机的请求调整成合适的形状,如下图所示:
流量控制有以下几个角度:
- 资源的调用关系,例如资源的调用链路,资源和资源之间的关系;
- 运行指标,例如 QPS、线程池、系统负载等;
- 控制的效果,例如直接限流、冷启动、排队等。
Sentinel 的设计理念是让用户自由选择控制的角度,并进行灵活组合,从而达到想要的效果。
3.2 熔断降级
什么是熔断降级
除了流量控制以外,降低调用链路中的不稳定资源也是 Sentinel 的使命之一。由于调用关系的复杂性,如果调用链路中的某个资源出现了不稳定,最终会导致请求发生堆积。这个问题和 Hystrix 里面描述的问题是一样的。
Sentinel 和 Hystrix 的原则是一致的:当调用链路中某个资源出现不稳定,例如,表现为 timeout,异常比例升高的时候,则对这个资源的调用进行限制,并让请求快速失败,避免影响到其它的资源进而产生雪崩的效果。
熔断降级设计理念
在限制的手段上,Sentinel 和 Hystrix 采取了完全不一样的方法。
Hystrix 通过线程池的方式,来对依赖(在我们的概念中对应资源)进行了隔离。这样做的好处是资源和资源之间做到了最彻底的隔离。缺点是除了增加了线程切换的成本,还需要预先给各个资源做线程池大小的分配。
Sentinel 对这个问题采取了两种手段:
-
通过并发线程数进行限制
和资源池隔离的方法不同,Sentinel 通过限制资源并发线程的数量,来减少不稳定资源对其它资源的影响。这样不但没有线程切换的损耗,也不需要您预先分配线程池的大小。当某个资源出现不稳定的情况下,例如响应时间变长,对资源的直接影响就是会造成线程数的逐步堆积。当线程数在特定资源上堆积到一定的数量之后,对该资源的新请求就会被拒绝。堆积的线程完成任务后才开始继续接收请求。 -
通过响应时间对资源进行降级
除了对并发线程数进行控制以外,Sentinel 还可以通过响应时间来快速降级不稳定的资源。当依赖的资源出现响应时间过长后,所有对该资源的访问都会被直接拒绝,直到过了指定的时间窗口之后才重新恢复。
3.3 系统负载保护
Sentinel 同时提供系统维度的自适应保护能力,它的最终目的是:保证系统不被拖垮的同时,进而保证系统的吞吐量。
防止雪崩,是系统防护中重要的一环。当系统负载较高的时候,如果还持续让请求进入,可能会导致系统崩溃,无法响应。在集群环境下,网络负载均衡会把本应这台机器承载的流量转发到其它的机器上去。如果这个时候其它的机器也处在一个边缘状态的时候,这个增加的流量就会导致这台机器也崩溃,最后导致整个集群不可用。
针对这个情况,Sentinel 提供了对应的保护机制,让系统的入口流量和系统的负载达到一个平衡,保证系统在能力范围之内处理最多的请求。
四、Sentinel 是如何工作的
Sentinel 的主要工作机制如下:
- 对主流框架提供适配或者显示的 API,来定义需要保护的资源,并提供设施对资源进行实时统计和调用链路分析
- 根据预设的规则,结合对资源的实时统计信息,对流量进行控制。同时,Sentinel 提供开放的接口,方便您定义及改变规则
- Sentinel 提供实时的监控系统,方便您快速了解目前系统的状态
从一般性流程来说,我们想要使用Sentinel来进行资源保护,主要分为几个步骤:
- 定义资源
主流框架都提供了默认的支持。例如使用SpringBoot开发的web应用,会自动定义所有http接口为Sentinel的资源
- 定义规则
这个就需要好好了解一下规则是什么,都有哪些了
- 检验规则是否生效
这个根据我目前的测试情况看来,我有点不确定官方提供的校验手段是否有效,你们看我【1.5 设置系统负载保护】内容就知道我意思了
先把可能需要保护的资源定义好,之后再配置规则。也可以理解为,只要有了资源,我们就可以在任何时候灵活地定义各种流量控制规则。在编码的时候,只需要考虑这个代码是否需要保护,如果需要保护,就将之定义为一个资源。
笔记正文
我当前项目结构:
├── shenadmin // 整个服务的顶级父项目├── shen-common // 项目公共模块├── shen-dependencies // 项目依赖模块├── shen-provider-apis // 项目对外暴露接口apis列表。provider直译:供应商├── shen-order-provider-api // 订单服-对外暴露接口apis列表├── shen-product-provider-api // 商品服-对外暴露接口apis列表├── shen-user-provider-api // 用户服-对外暴露接口apis列表├── shen-wallet-provider-api // 钱包服-对外暴露接口apis列表└── shen-servers // 项目微服务列表└── shen-product // 商品服└── shen-order // 订单服└── shen-user // 用户服└── shen-wallet // 钱包服
一、简单整合Sentinel
我学习整合的教程,来自SpringCloud Alibaba整合Sentinel的sample:传送门
另外,整合之前需要做一些工具准备。
- 安装Sentinel控制台(我在【1.3 配置限流规则:定义Sentinel规则】中有提到)
- 安装JMeter压测工具
1.1 添加maven依赖
显然,只有我的微服务项目才会用到Sentinel,所以,我只需要在shen-servers
下直接添加即可。而我早先已经添加了Spring Cloud Alibaba
的管理,所以,我只需要添加依赖即可,版本由前者兼容了。
<!-- sentinel-->
<dependency><groupId>com.alibaba.cloud</groupId><artifactId>spring-cloud-starter-alibaba-sentinel</artifactId>
</dependency>
1.2 接入限流埋点:定义Sentinel资源
【资源与规则】官方介绍传送门:基本使用 - 资源与规则
在此之前,需要给大家介绍并解释一下【埋点】这个概念。
Q1:什么是埋点?
埋点是一种数据采集技术,主要用于收集用户在应用或网站中的行为数据。通过在特定的页面或按钮上植入代码,可以监听用户的行为并进行收集上报。这样,开发者或数据分析师就能获取用户在使用产品过程中的具体行为数据,以进行数据分析、用户行为研究或产品优化等。简而言之,埋点是一种数据采集技术,实质是先监听软件应用运行过程中的事件,当需要关注的事件发生时进行判断和捕获。
翻译一下:【埋点】这个操作,其实在Sentinel里面,就是【定义资源】的过程。讲人话,就是设置哪些个url,甚至是方法需要被Sentinel管控。
可别刚说完就忘了Sentinel里面【资源】是什么东塞喔。我在【1.3 基本概念】中提到过,这是Sentinel里面一个核心概念
那么如何设置埋点呢?两种方式:
- 默认的
HTTP
。在Spring Cloud Alibaba
里面,默认会为所有HTTP
请求埋点,所以对我们Web开发用户来说,就不需要操心那么多了 - 自定义埋点。具体如何操作,可以参考官网的链接:基本使用(资源与规则)。不过自定义埋点操作,我稍微看了下,都是一些静态的、硬编码的方式,反正我是不喜欢这么干的。
1.3 配置限流规则:定义Sentinel规则
可得注意了啊,这里又是一个Sentinel核心概念噢。【资源与规则】官方介绍传送门:基本使用 - 资源与规则
Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。同时 Sentinel 也提供相关 API,供您来定制自己的规则策略。Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则 和 热点参数规则。
Sentinel 提供了两种配置限流规则的方式:【代码配置】和 【控制台配置】。根据官方《在生产环境中使用 Sentinel》的指引,还是建议在【控制台】中集中管理规则会比较合适,并且将规则推送之配置中心中。
本示例使用的方式为通过控制台配置。具体操作步骤如下:
1)下载安装Sentinel控制台
下载并启动Sentinel控制台。官方传送门:Sentinel 控制台
注意:控制台默认启动端口是8080,如果需要修改,启动的时候可以新增命令参数-Dserver.port=端口
。比如,我就修改为8090
端口
java -Dserver.port=8090 -jar sentinel-dashboard.jar
2)增加Sentinel配置
在所有的微服务应用中添加如下配置:
spring:cloud:sentinel:transport:# 下面的端口,dashboard: localhost:8090
因为我已经引入了Nacos配置中心,然后这个配置在我的实验环境中,应该是共享的,所以我就配置到了我在Nacos的application-conf.yaml
文件中。如下所示:
3)重启所有微服务
4)验证安装
上述步骤完成之后,就可以打开http://localhost:8090/尝试访问了。如下所示:
注意,如果您在控制台没有找到应用,请调用一下进行了 Sentinel 埋点的 URL 或方法,因为 Sentinel 使用了【懒加载】策略。
5)配置限流规则
我在我的实验环境这种,选择了shen-wallet
,然后点击流控规则
,新增流控规则
,内容如下:
为了让效果更明显,我做了如上的配置,意思是:当前/wallet/list
接口1秒内最大访问次数。
6)简单验证
快速刷新访问http://localhost:9032/wallet/list
,会出现如下所示的结果:
正常结果:
限流结果:(Blocked by Sentinel (flow limiting))
hold on hold on,我当然是比较建议下载JMeter来测试的,我自己就简单测试了
1.4 设置熔断规则
啊,很尴尬的一个点。如果你们的PRC使用的是OpenFeign
,那么可以直接参考这个官方示例,我截图给大家看吧。
但是,我在我的整合方案中,RPC使用的是Dubbo框架的Dubbo协议,所以,我得另外配置才能实验这个特性了。
1.4.1 Dubbo整合Sentinel
Dubbo整合Sentinel很简单,就是引入一个maven依赖就好了
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-dubbo-adapter</artifactId><version>版本</version>
</dependency>
通过引入这个项目,所有Dubbo接口也会被自动【埋点】。后面的所有规则设置,跟上面介绍的操作基本是一样的。给你们看看我的效果:
1)Dubbo接口被Sentinel管理
2)对Dubbo资源做降级处理
1.5 设置系统负载保护
这一点我暂时搁置一下,MD,卡了我一天了,从昨天到现在,我不知道自己哪里没有设置对。
反正就是没效果。不知道是不是版本的问题,我百度别人的Sentinel Admin跟我的不是很像。为了校验我的规则是否生效,我采用了如下方式:
- 通过端点信息查看,规则是设置成功的(Endpoint)
- 我设置了最简单的入口QPS限制,通过压测工具发送N多条请求发现调用是成功的,反过来证明我的系统负载设置失败
- 通过实时监控发现,
b_qps
指标又是正常的,证明系统负载设置成功 - 根据秒级监控日志,看每个指标也是合理的,证明系统负载设置成功
- 自定义了BlockedException想要捕获异常日志,但是没有发现系统保护异常
SystemBlockException
暂时性放弃了xdm
二、概念补充:Sentinel规则
我在学习的过程中,发现,Sentinel的规则还是非常重要的,只有熟练的掌握了这些规则,我们才能在实际的生产中,做更丰富的流控策略。
2.1 规则的种类
Sentinel 的所有规则都可以在内存态中动态地查询及修改,修改之后立即生效。同时 Sentinel 也提供相关 API,供您来定制自己的规则策略。
总的来说,Sentinel 支持以下几种规则:流量控制规则、熔断降级规则、系统保护规则、来源访问控制规则 和 热点参数规则。
2.1.1 流量控制规则 (FlowRule)
重要属性:
PS:同一个资源可以同时有多个限流规则
通过代码定义流量控制规则:
理解上面规则的定义之后,我们可以通过调用 FlowRuleManager.loadRules()
方法来用硬编码的方式定义流量控制规则,比如:
private static void initFlowQpsRule() {List<FlowRule> rules = new ArrayList<>();FlowRule rule1 = new FlowRule();rule1.setResource(resource);// Set max qps to 20rule1.setCount(20);rule1.setGrade(RuleConstant.FLOW_GRADE_QPS);rule1.setLimitApp("default");rules.add(rule1);FlowRuleManager.loadRules(rules);
}
2.1.2 熔断降级规则 (DegradeRule)
重要属性:
PS:同一个资源可以同时有多个降级规则
通过代码定义熔断降级规则:
理解上面规则的定义之后,我们可以通过调用 DegradeRuleManager.loadRules()
方法来用硬编码的方式定义流量控制规则。
private static void initDegradeRule() {List<DegradeRule> rules = new ArrayList<>();DegradeRule rule = new DegradeRule(resource);.setGrade(CircuitBreakerStrategy.ERROR_RATIO.getType());.setCount(0.7); // Threshold is 70% error ratio.setMinRequestAmount(100).setStatIntervalMs(30000) // 30s.setTimeWindow(10);rules.add(rule);DegradeRuleManager.loadRules(rules);
}
2.1.3 系统保护规则 (SystemRule)
Sentinel 系统自适应限流从整体维度对应用入口流量进行控制,结合应用的 Load、CPU 使用率、总体平均 RT、入口 QPS 和并发线程数等几个维度的监控指标,通过自适应的流控策略,让系统的入口流量和系统的负载达到一个平衡,让系统尽可能跑在最大吞吐量的同时保证系统整体的稳定性。
重要属性:
通过代码定义系统保护规则:
理解上面规则的定义之后,我们可以通过调用 SystemRuleManager.loadRules()
方法来用硬编码的方式定义流量控制规则:
private void initSystemProtectionRule() {List<SystemRule> rules = new ArrayList<>();SystemRule rule = new SystemRule();rule.setHighestSystemLoad(10);rules.add(rule);SystemRuleManager.loadRules(rules);
}
2.1.4 访问控制规则 (AuthorityRule)
很多时候,我们需要根据调用方来限制资源是否通过,这时候可以使用 Sentinel 的访问控制(黑白名单)的功能。黑白名单根据资源的请求来源(origin)限制资源是否通过,若配置白名单则只有请求来源位于白名单内时才可通过;若配置黑名单则请求来源位于黑名单时不通过,其余的请求通过。
授权规则,即黑白名单规则(AuthorityRule)非常简单,主要有以下配置项:
resource
:资源名,即限流规则的作用对象limitApp
:对应的黑名单/白名单,不同 origin 用 , 分隔,如 appA,appBstrategy
:限制模式,AUTHORITY_WHITE 为白名单模式,AUTHORITY_BLACK 为黑名单模式,默认为白名单模式
2.1.5 热点规则 (ParamFlowRule)
热点规则的配置略显麻烦一点。首先需要理解,什么是热点
热点:
何为热点?热点即经常访问的数据。很多时候我们希望统计某个热点数据中访问频次最高的 Top K 数据,并对其访问进行限制。比如:
- 商品 ID 为参数,统计一段时间内最常购买的商品 ID 并进行限制
- 用户 ID 为参数,针对一段时间内频繁访问的用户 ID 进行限制
热点参数限流会统计传入参数中的热点参数,并根据配置的限流阈值与模式,对包含热点参数的资源调用进行限流。热点参数限流可以看做是一种特殊的流量控制,仅对包含热点参数的资源调用生效。
限流原理:
Sentinel 利用 LRU 策略统计最近最常访问的热点参数,结合令牌桶算法来进行参数级别的流控
在我们项目中,如果想要使用改规则,还需要额外引入maven依赖:
<dependency><groupId>com.alibaba.csp</groupId><artifactId>sentinel-parameter-flow-control</artifactId><version>x.y.z</version>
</dependency>
重要属性:
学习总结
感谢
- 感谢Alibaba Sentinel的文章《在生产环境中使用 Sentinel》
相关文章:

【分布式微服务专题】从单体到分布式(四、SpringCloud整合Sentinel)
目录 前言阅读对象阅读导航前置知识一、什么是服务雪崩1.1 基本介绍1.2 解决方案 二、什么是Sentinel2.1 基本介绍2.2 设计目的2.3 基本概念 三、Sentinel 功能和设计理念3.1 流量控制3.2 熔断降级3.3 系统负载保护 四、Sentinel 是如何工作的 笔记正文一、简单整合Sentinel1.1…...

RHCE9学习指南 第19章 网络时间服务器
19.1 时间同步的必要性 对于一些服务来说对时间要求非常严格,例如,图19-1所示由三台服务器搭建的ceph集群。 图19-1 三台机器搭建的集群对时间要求比较高 这三台服务器的时间必须要保持一样,如果不一样,就会显示报警信息。那么…...

大模型 RAG 问答技术架构及核心模块盘点:从 Embedding、prompt-embedding 到 Reranker
对于RAG而言,2023年已经出现了很多工作,草台班子有了一堆,架构也初步走通,2024年应该会围绕搜索增强做更多的优化工作。 因此我们今天来系统回顾下RAG中的模块,包括一些架构,文本嵌入embedding等ÿ…...

基于Selenium+Python的web自动化测试框架
一、什么是Selenium? Selenium是一个基于浏览器的自动化测试工具,它提供了一种跨平台、跨浏览器的端到端的web自动化解决方案。Selenium主要包括三部分:Selenium IDE、Selenium WebDriver 和Selenium Grid。 Selenium IDE:Firefo…...

LeetCode刷题--- 地下城游戏
个人主页:元清加油_【C】,【C语言】,【数据结构与算法】-CSDN博客 个人专栏 力扣递归算法题 http://t.csdnimg.cn/yUl2I 【C】 http://t.csdnimg.cn/6AbpV 数据结构与算法 http://t.csdnimg.cn/hKh2l 前言:这个专栏主要讲述动…...

【sklearn练习】鸢尾花
一、 import numpy as np from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier 第二行:导入datasets数据集 第三行:train_test_split 的作用是将数据集随机分配…...

STM32的USB设备库
适用范围:“on the STM32F10xxx,STM32F37xxx, STM32F30xxx and STM32L15xxx devices.” STM32_USB-FS-Device_Lib_V4.0.0.rar(访问密码:1666)https://url48.ctfile.com/f/33868548-1000799917-a5409d?p1666 适用范围࿱…...

整数对最小和(100%用例)C卷 (JavaPythonC++Node.jsC语言)
给定两个整数数组 array1 、 array2 ,数组元素按升序排列。假设从 array1 、 array2 中分别取出一个元素可构成一对元素,现在需要取出 k 对元素,并对取出的所有元素求和,计算和的最小值 注意:两对元素如果对应于 array1 、 array2 中的两个下标均相同,则视为同一对元素。…...

QT笔记 - 加载带有提升为自定义部件类的“.ui“文件 - 重写QUiLoader::createWidget()函数
说明 如果ui设计中有提升过小部件,则无法直接使用QUiLoader加载。完成加载需要重新实现UiLoader::createWidget()函数。 函数 virtual QWidget * QUiLoader::createWidget(const QString & className, QWidget * parent Q_NULLPTR, const QString & name…...

开启Android学习之旅-2-架构组件实现数据列表及添加(kotlin)
Android Jetpack 体验-官方codelab 1. 实现功能 使用 Jetpack 架构组件 Room、ViewModel 和 LiveData 设计应用;从sqlite获取、保存、删除数据;sqlite数据预填充功能;使用 RecyclerView 展示数据列表; 2. 使用架构组件 架构组…...

leetcode 动态规划(最后一块石头的重量II、目标和、一和零)
1049.最后一块石头的重量II 力扣题目链接(opens new window) 题目难度:中等 有一堆石头,每块石头的重量都是正整数。 每一回合,从中选出任意两块石头,然后将它们一起粉碎。假设石头的重量分别为 x 和 y,且 x < …...

JavaWeb-HTTP
一、概念 HTTP:HyperText Transfer Protocol,超文本传输协议。读者应该不是第一次接触这个名词,但可能仍然不是很理解,笔者将逐一解释。 HyperText(超文本):根据维斯百科,Hypertex…...

算法训练营第四十二天|动态规划:01背包理论基础 416. 分割等和子集
目录 动态规划:01背包理论基础416. 分割等和子集 动态规划:01背包理论基础 文章链接:代码随想录 题目链接:卡码网:46. 携带研究材料 01背包问题 二维数组解法: #include <bits/stdc.h> using namesp…...

前端 JS篇快问快答
问题:常见的特殊字符(不包括空格\s) 正则表达式为: 回答:/[!#$%^&*()\-_{};:",.<>/?[\]~|]/ (加粗的紫色字符都是特殊字符) 问题:常见的特殊字符(包括…...

vue/vue3/js来动态修改我们的界面浏览器上面的文字和图标
前言: 整理vue/vue3项目中修改界面浏览器上面的文字和图标的方法。 效果: vue2/vue3: 默认修改 public/index.html index.html <!DOCTYPE html> <html lang"en"><head><link rel"icon" type"image/sv…...

MobaXterm SSH 免密登录配置
文章目录 1.简介2.SSH 免密登录配置第一步:点击 Session第二步:选择 SSH第三步:输入服务器地址与用户名第四步:设置会话名称第五步:点击 OK 并输入密码 3.密码管理4.小结参考文献 1.简介 MobaXterm 是一个功能强大的终…...

霍兰德职业兴趣测试:找到与你性格匹配的职业
霍兰德职业兴趣理论 约翰霍兰德(John Holland)是美国约翰霍普金斯大学心理学教授,美国著名的职业指导专家。他于1959年提出了具有广泛社会影响的职业兴趣理论。认为人的人格类型、兴趣与职业密切相关,兴趣是人们活动的巨大动力&a…...

LVGL学习笔记 显示和隐藏 对象的属性标志位 配置
在显示GUI的过程中需要对某些对象进行临时隐藏或临时显示,因此需要对该对象的FLAG进行配置就可以实现对象的显示和隐藏了. 调用如下接口可以实现: lv_obj_add_flag(user_obj, LV_OBJ_FLAG_HIDDEN);//隐藏对象lv_obj_clear_flag(user_obj, LV_OBJ_FLAG_HIDDEN);//取消隐藏实现的…...

cuda上使用remap函数
在使用opencv中的remap函数时,发现运行时间太长了,如果使用视频流进行重映射时根本不能实时,因此只能加速 1.使用opencv里的cv::cuda::remap函数 cv::cuda::remap函数头文件是#include <opencv2/cudawarping.hpp>,编译ope…...

【JaveWeb教程】(18) MySQL数据库开发之 MySQL数据库设计-DDL 如何查询、创建、使用、删除数据库数据表 详细代码示例讲解
目录 2. 数据库设计-DDL2.1 项目开发流程2.2 数据库操作2.2.1 查询数据库2.2.2 创建数据库2.2.3 使用数据库2.2.4 删除数据库 2.3 图形化工具2.3.1 介绍2.3.2 安装2.3.3 使用2.2.3.1 连接数据库2.2.3.2 操作数据库 2.3 表操作2.3.1 创建2.3.1.1 语法2.3.1.2 约束2.3.1.3 数据类…...

ElasticSearch学习笔记-SpringBoot整合Elasticsearch7
项目最近需要接入Elasticsearch7,顺带记录下笔记。 Elasticsearch依赖包版本 <properties><elasticsearch.version>7.9.3</elasticsearch.version><elasticsearch.rest.version>7.9.3</elasticsearch.rest.version> </propertie…...

[足式机器人]Part2 Dr. CAN学习笔记 - Ch02动态系统建模与分析
本文仅供学习使用 本文参考: B站:DR_CAN Dr. CAN学习笔记 - Ch02动态系统建模与分析 1. 课程介绍2. 电路系统建模、基尔霍夫定律3. 流体系统建模4. 拉普拉斯变换(Laplace)传递函数、微分方程4.1 Laplace Transform 拉式变换4.2 收…...

【一周年创作总结】人生是远方的无尽旷野呀
那一眼瞥见的伟大的灵魂,却似模糊的你和我 文章目录 📒各个阶段的experience🔎大一寒假🔎大一下学期🔎大一暑假🔎大二上学期(现在) 🍔相遇CSDN🛸自媒体&#…...

金融帝国实验室(Capitalism Lab)V10版本游戏平衡性优化与改进
即将推出的V10版本中的各种游戏平衡性优化与改进: ————————————— 一、当玩家被提议收购一家即将破产的公司时,显示商业秘密。 当一家公司濒临破产,玩家被提议收购该公司时,如果玩家有兴趣评估该公司,则无…...

[SpringBoot]接口的多实现:选择性注入SpringBoot接口的实现类
最近在项目中遇到两种情况,准备写个博客记录一下。 情况说明:Service层一个接口是否可以存在多个具体实现,此时应该如何调用Service(的具体实现)? 其实之前的项目中也遇到过这种情况,只不过我采…...

北京大学 wlw机器学习2022春季期末试题分析
北京大学 wlw机器学习2022春季期末试题分析 前言新的开始第一题第二题第三题 前言 你好! 这是你第一次使用 Markdown编辑器 所展示的欢迎页。如果你想学习如何使用Markdown编辑器, 可以仔细阅读这篇文章,了解一下Markdown的基本语法知识。 新的开始 第…...

前端文件下载方法(包含get和post)
export const downloadFileWithIframe (url, name) > {const iframe document.createElement(iframe);iframe.style.display none; // 防止影响页面iframe.style.height 0; // 防止影响页面iframe.name name;iframe.src url;document.body.appendChild(iframe); // 这…...

高性能、可扩展、支持二次开发的企业电子招标采购系统源码
在数字化时代,企业需要借助先进的数字化技术来提高工程管理效率和质量。招投标管理系统作为企业内部业务项目管理的重要应用平台,涵盖了门户管理、立项管理、采购项目管理、采购公告管理、考核管理、报表管理、评审管理、企业管理、采购管理和系统管理等…...

2645. 构造有效字符串的最少插入数
Problem: 2645. 构造有效字符串的最少插入数 文章目录 解题思路解决方法复杂度分析代码实现 解题思路 解决此问题需要确定如何以最小的插入次数构造一个有效的字符串。首先,我们需要确定开头的差距,然后决定中间的补足,最后决定末尾的差距。…...

C#,快速排序算法(Quick Sort)的非递归实现与数据可视化
排序算法是编程的基础。 常见的四种排序算法是:简单选择排序、冒泡排序、插入排序和快速排序。其中的快速排序的优势明显,一般使用递归方式实现,但遇到数据量大的情况则无法适用。实际工程中一般使用“非递归”方式实现。 快速排序(Quick Sor…...