高可用 Go 服务开发

news/2024/9/13 11:22:58/ 标签: 开发语言, Go, 高可用

        高可用的含义是尽量减少服务的不可用(日常维护或者突发系统故障)时长,提升服务的可用时长。如何衡量一个服务的可用性呢?或许你也听说过,通常企业可能会要求服务的可用性能能够达到三个 9(也就是 99.9%)或者 4个 9 (也就是 99.99%),可是你知道这是如何计算的吗?需要重点强调的是,可用性是每一个 Go 开发者都必须关注的事情。

1. 可用性定义与高可用性三板斧

        我们的目标是构建高可用Go 服务,那如何定义服务的可用性呢?我们又该如何提升服务的可用性呢?其实这些都是有固定套路的。

1.1 可用性定义

        我们总说提升服务的可用性,可是如何衡量服务的可用性呢?如果没有一个量化的指标,你又怎么知道服务的可用性是提升了还是降低了。我们可以按照下面的方式定义服务的可用性:

        其中 MTTF (Mean Time To Failure) 指的是服务的平均无故障时间,即服务从正常运行到出现故障的平均时间:MTTR ( Mean Time To Repair)指的是服务的平均修复时间(故障时间),即服务从出现故障到修复成功的平均时间。根据这个定义,我们可以计算出在不同的可用性目标下,全年服务可以接受的最长故障时间,如下表所示:

可用性级别可用性目标全年故障时间每天故障时间
190%36.5天2.4h
299%3.65 天14min
399.9%8.76h86s
499.99%53min8.6s

        当我们的可用性目标是 4 个 9(也就是 99.99%)时,全年故障时间为 53min,每天故障时间为 8.6s。也就是说,如果全年的故障时间超过 53min,那么当年的可用性指标肯定就无法达到 99.99% 了。

        根据上述可用性的定义,提升服务可用性最直观的方式就是减少故障时长。如何减少呢?我们可以从两方面入手:

1)预防:尽可能避免服务发生故障。

2)故障处理:当服务发生故障时,尽可能快速地恢复服务的正常运行。当然,这样的描述还是过于泛化,具体的可用性提升方案还需要进一步细化,可以参考下表:

预防故障处理
质量提升

1. 研发质量提升:比如技术方案评审,代码评审,单元测试等

2. 测试质量提升:比如白盒测试,自动化测试,仿真环境建设等

变更管控

1. 变更窗口:比如业务高峰期禁止线上变更

2. 任何变更都需要双重检查,都需要有回滚方案,都需要有检查清单

3. 灰度发布 ,小流量发布

容错设计

1. 资源隔离:比如服务部署隔离、网关侧隔离、数据库隔离等

2. 错误隔离:比如请求级的错误隔离、进程级的错误隔离、服务级的错误隔离等

3. 限流、熔断与降级:非核心功能可降级,非核心依赖可熔断

4. 故障演练

冗余设计

1. 避免单点:主备/集群化部署,服务可快速扩容

2. 容量冗余:性能评估与性能压测

3. 异地多活

发现

1.核心业务监控与报警:比如订单服务、支付服务

2. 服务可用性监控与报警:比如服务错误日志、网关侧异常状态码等

3. 基本指标的监控与报警:比如 CPU、内存、网络等

定位

1. 日志与全链路追踪:业务日志、网关侧访问日志、全链路日志

2. 监控:多维度多特征监控、容量监控、基本指标监控、端到端监控

止损

1. 流量调度:主要针对集群故障、机房故障

2.限流、熔断与降级:紧急限流、非核心功能降级、非核心依赖熔断

3. 变更回滚:针对变更引起的异常

4. 快速扩容:针对容量不足的情况

5. 服务重启

恢复

1. 复原:问题修复,数据修复,执行过的止损操作还原

2. 复盘:分析根本原因,制订改进计划

1.2 高可用三板斧

        高可用三板斧指的是限流、熔断与降级。限流是通过对并发请求进行限速来保护自身服务;熔断是为了避免依赖的第三方服务影响自身服务;降级是通过牺牲非核心功能来保障核心功能。为什么要单独介绍限流、熔断与降级呢?因为这是构建高可用服务不可缺少的三种手段。下面将分别介绍限流、熔断与降级的基本原理。

1.2.1 限流

        首先来说限流,限流是通过对并发请求进行限速来保护自身服务。当请求速率超过限制速率时,服务端可以直接拒绝请求(返回固定的错误,或者定向到错误页面),或者将请求排队等待后续处理。常见的限流方式有:限制瞬时并发数,限制单位时间窗口内的平均速率。当然,也可以根据网络连接数、网络流量、CPU 和 内存负载等进行限流。

        以限制单位时间窗口内的平均速率为例,常用的限流算法有计数器算法、漏桶算法、令牌桶算法。下面我们详细介绍这几种限流算法。

(1)计数器算法

        计数器算法是限流算法中最简单且最容易实现的一种算法。例如,假设我们规定某个接口的平均每秒访问速率不能超过 1000 次,为了实现这个限制,我们可以为该接口维护一个计数器,其有效时间为 1s。每当有请求到达时,计数器就会加 1,如果计数器的值超过了 1000,就表示请求速率超过了限制值。

        需要说明的是,尽管这个算法很简单,但准确度却很差。我们将 1s 的时间段划分为 1000ms。假设在第 999ms 时,有 1000 个请求到达,显然不会触发限流(0~1000ms 是一个计数周期)。而在第 1001 ms 时,又有 1000 个请求到达,同样不会出触发限流(1000~2000ms是一个计数周期)。但是你会发现,瞬时的请求速率非常高。在从 999ms 到 1001ms 这 2ms 内,就需要处理 2000 个请求,这可能已经超过了服务的处理能力。

(2)漏桶算法

漏桶算法的基本原理可以参考下图,

有一个固定容量的漏桶,该漏桶可以按照固定速率流出水滴,如果漏桶是空的,则不会流出水滴。流入漏桶的水流速度(请求速率)是随意的,如果流入的水(请求)超出了漏桶的容量,则会溢出(请求被丢失)。可以看到,漏桶算法的最大请求速率是恒定的。

(3)令牌桶算法

        令牌桶算法示意图如下所示:

        思考一下,如果令牌桶的容量是 0,并且排队等待的请求队列长度是有限制的,这时候令牌桶算法是不是和漏桶算法非常类似呢?

1.2.2. 熔断与降级

        熔断是为了避免依赖的第三方服务影响自身服务,如何避免呢?当然是不再依赖异常的第三方服务了,比如当需要请求第三方服务时,直接返回默认的数据即可。为什么需要熔断呢?假设有这么一个业务场景:A 服务依赖了 B 服务,B 服务的平均响应时间是 100ms,此时 A 服务的 QPS 可以达到 1 万;某一个业务高峰, B 服务突然变慢了,平均响应时间变成了 500ms, 此时 A 服务的平均响应时间肯定也会变长,那么其 QPS 还能达到 1 万吗?通常情况下远远达不到的。

        这还不是最糟糕的,要知道这可是处于业务高峰时期,A 服务的性能变差之后,大量的业务请求将会失败,而通常请求失败时还会有一些重试(用户重试或者自动重试),这就导致 A 服务需要承担更大的请求压力,极端情况下甚至可能会压垮 A 服务,进而拖垮 B 服务。

        当然,如果 B 服务是 A 服务的弱依赖(也就是说,即使没有 B 服务,A 服务也可以正常运行),当 B 服务出现异常(比如变慢)时,A 服务可以采取熔断策略,不再依赖 B 服务,以此保证自身服务的正常运行。

        最后说一下降级,降级的目的是降低系统压力,保障核心服务的正常运行。比如每年的双 11、618等购物节,你会发现当天这些电商平台的部分功能是不可用的(被降级了),而这些功能基本上是不会影响用户的购物体验的。通常什么场景下需要降级呢?比如业务高峰期,机器资源不足时,可以将非核心服务降级,以保障核心服务的资源充足;比如系统出现异常并且无法快速定位时,同样可以将非核心服务降级,以避免非核心服务影响核心服务。

 2. 流量治理组件 Sentinel

        Sentinel 是阿里技术团队开源的流量治理组件,其主要以流量为切入点,从流量控制、流量整形、熔断降级、系统自适应过载保护等多个维度来帮助开发者保障服务的稳定性。2012 年 Sentinel 就诞生了,只是这时候只有 java 版本,直到 2020 年阿里团队才推出了 Go 版本。

2.1 Sentinel 快速入门

        在讲解Sentinel 的使用之前,先介绍一个基本概念:资源(resource),这是 Sentinel 中的最核心概念之一。Sentinel 中所有的限流熔断机制都是基于资源生效的,不同资源的限流熔断规则互相隔离互不影响。在 Sentinel 中,用户可以灵活地定义资源,比如可以将应用、接口、函数,甚至是一段代码等定义为一种资源,而流量治理的目的就是保护资源如预期一样运行。

        用户可以通过 Sentinel 提供的接口将资源访问包装起来,这一步称为 “埋点”。每个埋点都有一个资源名称(resource),代表触发了这个资源的调用或访问,有了资源埋点之后,我们就可以针对资源埋点配置流量治理规则。Sentinel 支持多种类型的流量治理规则,如流量控制规则、流量隔离规则、熔断降级规则、自适应过载保护规则以及热点参数流量控制规则。

        那么如何使用 Sentinel 呢?可以参考 Sentinel 官方给出的基于 QPS 限流示例,代码如下所示:

Go">func main(){//务必先进行初始化err := sentinel.InitDefault()//配置一条限流规则_,err = flow.LoadRules([]*flow.Rule){{Resource:	"some-test",Threshold:	10,.....},})//模拟并发访问for i :=0; i <10;i++{go func(){for {//埋点逻辑,埋点资源名称为 some-teste,b := sentinel.Entry("some-test")if b != nil {//请求被拒绝,在此进行处理}else {//请求允许通过,此直编写业务逻辑fmt.Println(util.CurrentTimeMillis(),"Passed")e.Exit() //务比何证业务结束后调用 Exit}}}()}
......
}

 

2.2 流量控制

        流量控制的目的是避免服务被瞬时的流量高峰冲垮,其原理是根据令牌计算策略来计算可用令牌的资源,并根据流量控制策略对请求进行控制(拒绝或者排队等待)。Sentinel 的流量控制规则定义如下所示:

Go">type Rule struct {ID stringResource string										//规则IDTokenCalculateStrategy TokenCalculateStrategy		//资源名称ControlBehavior	ControlBehavior						//令牌计算策略Threshold				float64						//流量控制行为MaxQueueingTimeMS		uint32						//限流阈值WarmUpPeriodSec			uint32						//请求排队的最长等待时间WarmUpColdFactor		unit32						//预热的时间长度StatIntervalInMs 		uint32						//预热因子,该值会影响预热速度LowMemUsageThreshold 	int64						//流量控制器的统计周期,单位是msHighMemUsageThreshold 	int64						//内存使用小于低水位时的限流阈值MemLowWaterMarkBytes 	int64						//内存低水位MemHighWaterMarkBytes 	int64						//内存高水位
}

        流量控制规则的字段还是比较多的,这里就不一一介绍了。我们主要介绍一下令牌计算策略、流量控制行为以及内存自适应流量控制。

 Sentinel 支持两种类型的令牌计算策略。

2.3 系统自适应流量控制

        Sentinel 支持系统自适应流量控制,什么意思呢?就是结合系统的负载、CPU 利用率、服务的入口 QPS、服务的平均响应时间、并发数等几个维度的监控指标,通过自适应的方式进行流量控制。系统自适应流量控制的目的是平衡入口流量与系统负载,在保障系统稳定性的前提下使得系统尽可能地对外提供服务。需要注意的是,系统自适应流量控制是面向整个服务的,而不是单个接口的,并且仅对入口流量生效。

Sentinel 系统自适应流量控制目前支持 5 种类型的流量控制方式,定义如下:

1)负载:负载是对 CPU 工作量的度量,指的是单位时间内系统中的平均活跃进程数;负载可以用 3 个指标衡量,load1、load5 与 load15,分别表示过去 1min、5min 与 15min 的平均负载,Sentinel 使用的是 load1 来进行系统自适应流量控制。

2)CPU 利用率:CPU 利用率用于衡量 CPU 的繁忙程度,其定义是除了空闲时间外的其他时间占总 CPU 时间的百分比。

3)平均响应时间:Sentinel 会统计所有入口流量总的响应时间,总响应时间除以总的请求数就是平均响应时间。

4)并发数:当请求通过时并发数加1,当请求执行结束时并发数减1。

5)入口 QPS:入口 QPS 的统计同样是基于滑动窗口实现的。

        Sentinel 系统自适应流量控制的规则定义如下所示:

Go">type Rule struct {ID 				string				//规则IDMetricType 		MetricType			//流量控制指标类型TriggerCount 	float64				//流量控制触发阈值Strategy 		AdaptiveStrategy	//自适应流量控制策略
}

        在上面的代码中,字段 MetricType 就是我们介绍的流量控制指标类型,字段 Strategy 表示自适应流量控制策略。Sentinel 提供了两种类型的自适应流量控制策略:NoAdaptive 与 BBR。NoAdaptive 类型的自适应流量控制策略非常简单,只需要对应的指标,如负载大于阈值就拒绝请求。那什么是 BBR 呢?思考一下,仅仅根据系统负载或者 CPU 利用率进行流量控制合适吗?换一个思路,系统负载或者 CPU 利用率其实是结果,是系统容量无法支持高并发请求的结果。如果我们仅仅根据系统负载或者 CPU 利用率进行流量控制,就始终存在一定的延迟。

        为了解决上面的问题,Sentinel 参考了 TCP 拥塞控制算法(BBR)。TCP 拥塞控制算法的初衷同样是在保证通信质量的前提下尽可能提升链路带宽利用率。该算法认为当同时满足最大带宽和最小延迟时,整个网络处于最优工作状态,此时网络中的数据包总量等于最大带宽乘最小时延。参考 TCP 拥塞控制算法,Sentinel 实现的 BBR 自适应流量控制策略如下所示:

Go">func checkBbrSimple() bool {concurrency := stat.InboundNode().CurrentConcurrency()minRt := stat.InboundNode().MinRT()maxComplete := stat.InboundNode().GetMaxAvg(base.MetricEventComplete)if concurrency > 1 && float64(concurrency) > maxComplete*minRt/1000.0 {return false}return true
}

        在上面的代码中,变量 concurrency 表示当前系统处理的并发请求数,minRt表示最小时延,maxComplete 表示每秒最大处理的请求数。这一逻辑与 TCP 拥塞控制算法是一致的。

        系统自适应流量控制的使用还是比较简单的,只需要定义好流量控制规则就可以了,只是别忘了在请求入口将所有资源的访问包起来。

 2.4 熔断降级

        熔断与降级其实是非常类似的,本质上都是切断不稳定的弱依赖服务调用(只是熔断是从服务消费者视角出发的,降级是从服务提供者视角出发的),所以 Sentinel 将熔断降级合成了一种规则。

2.5 Sentinel 原理浅析

        Sentinel 为我们提供了多种流量治理策略,如流量控制、系统自适应流量控制、熔断降级等。但是,如果 Sentinel 原生的流量治理策略无法满足业务需求,该怎么办呢?这时候有可能就需要我们自定义流量治理策略了,如何自定义呢?这就需要我们对 Sentinel 的原理有一定了解。

        Sentinel 的主框架是基于责任链模式实现的,每一个请求都需要经过多个请求处理器,理论上每一个请求处理器都会根据自身的流量治理策略以及流量治理规则判断是否允许请求通过。当然,Sentinel 其实提供了三种类型的请求处理器:第一种请求处理器主要用于执行一些初始化操作;第二种请求处理器就是 Sentinel 提供的各种类型的流量治理策略;第三种请求处理器主要用于统计指标。这三种类型的请求处理器接口定义如下:

3. Go 服务监控

        在故障处理时,完善的监控与报警体系可以帮助我们快速地发现问题与定位问题。对 Go 服务而言,如何监控 Go 服务的核心指标呢?比如协程数、内存使用量、线程数等。

3.1 运行时监控

        如何监控 Go 服务的运行时指标呢?

        第一步,当然是采集 Go 服务的运行时指标了,常用的运行时指标包括线程数、协程数、内存使用量、GC耗时等。如何采集呢?幸运的是,Go 语言为我们提供了 SDK,通过这些 SDK 我们可以很方便地获取到这些运行时指标

        第二步,如何导出与查看这些运行时指标呢?我们可以借助 Prometheus,这是一款开源的监控与报警系统,并且提供了多种语言的客户端库,其中就包括 Go 语言。

3.2 自定义监控

        3.1 小节讲解了如何监控 Go 服务的运行时指标,那如果我们想自定义一些监控指标该如何实现呢?比如服务或者接口的访问 QPS、响应时间等。这就需要我们对 Prometheus 的几种指标类型以及 Prometheus 客户端库的使用有一些了解。

4. 其他

        在 Go 项目开发过程中,有两个细节特别容易忽视:超时控制与错误处理。不合理的超时时间错误处理可能导致服务因为一些轻微的异常而崩溃。因此,在依赖第三方资源时一定要注意设置合理的的超时时间,并且在项目开发过程中要有完善的错误处理机制。

4.1 超时控制

        大部分Web 服务通常都会依赖 HTTP 服务、数据库以及 Redis等。下面将分别介绍在依赖这三种类型的资源时,如何设置合理的超时时间。

4.1.1 HTTP服务

        当我们使用 Go 语言原生的 HTTP 客户端访问第三方服务时,可以通过两种方式设置超时时间。第一种方式是基于 HTTP 客户端的 Timeout 字段实现的,第二种方式是基于上下文 context 实现的。

4.1.2 数据库

        Go 服务操作数据库通常都是基于长连接,因此数据库的超时时间可以分为建立连接的超时时间与处理请求的超时时间。

4.1.3 Redis

        Go 服务操作 Redis 通常是基于长连接,因此 Redis 的超时时间也分为建立连接的超时时间与处理请求的超时时间。

4.2 错误处理

        Go 语言将错误分为两种类型:一种是普通错误,也就是我们常用的类型 error; 一种是严重错误,通常我们用关键字 panic 声明发生了严重错误。下面分别介绍这两种类型的错误。

4.2.1 error

        在实际项目开发过程中,你会发现很多函数都会有多个返回值,通常第一个返回值用于返回真正的结果,第二个返回值是类型 error,表示是否发生了错误。代码如下所示:

Go">resp,err := client.Do(req)
if err != nil {fmt.Println(fmt.Sprintf("client error:%v",err))return
}

        在上面的代码中,我们在调用一些函数之后通常都会判断返回值 error 是否为空:如果不为空,则说明发生了错误,此时需要执行一些错误处理操作,比如记录错误日志等;如果为空,说明函数调用成功,则继续执行后续流程。

4.2.2 panic

        关键字 panic 通常用于声明发生了严重错误,需要特别注意的是,panic 会导致程序异常退出。以下面程序为例:

Go">package mainimport "fmt"func main() {fmt.Println("test1 start")panic("this is a panic")fmt.Println("panic 1")
}

执行上面的程序之后,控制台会输出如下信息:

Go">test1 start
panic: this is a panic//协程栈桢
goroutine 1 [running]:
main.main()//程序异常退出
错误: 进程退出代码 2.

        参考上面的输出结果,当我们通过 panic 声明错误之后,程序直接异常退出了,panic 语句之后的输出语句并没有执行。幸运的是,当程序因为 panic 异常退出时,会输出异常信息以及协程栈帧,通过这些信息我们基本上就能排查出问题所在了。当然,在实际项目开发过程中,我们可能需要避免程序因为 panic 异常退出,毕竟不能因为一个请求异常影响整个服务,这时候可以使用延迟调用defer 捕获异常,代码如下所示:

Go">//该语句在调用函数 test 之前
defer func(){fmt.Println("defer 1")if rec := recover(); rec != nil {fmt.Println(rec)}fmt.Println("defer 2")
}()

程序输出如下: 

Go">test1 start
defer 1
this ia a panic
defer 1
//程序正常退出
Process finished with the exit code 0

        在上面的代码中,当我们使用延迟调用 defer 捕获异常之后,程序就能够从 defer 语句开始恢复执行,最终程序也会正常退出。

        最后补充一下,在一些业务场景中,当发生错误时,可能会进行重试(重试可以在一定程度上解决部分问题),

        思考一下,为什么需要采用指数退避算法进行重试呢?因为当第三方服务返回错误时,如果我们立即重试,很有可能还会得到一个错误的响应,并且频繁地重试对第三方服务的压力也比较大,所以可以稍微等一段时间再重试。

        另外需要注意的是,重试需谨慎,不合理的重试可能会导致服务的雪崩。为什么呢?这里举两个具体的例子。

        第一个例子,假设 A 服务依赖了 B 服务,在某个业务高峰期间,B 服务出现了异常(大量返回错误或者大量超时),此时 A 服务在调用 B 服务时,发现返回了错误,于是又进行重试。这会导致什么呢?A 服务的重试会进一步增加 B 服务的负载,甚至导致 B 服务的崩溃。

        第二个例子,整个请求的链路其实是非常复杂的,一个客户端请求到达 A 服务可能需要经过全站加速,接入层网关,容器 Ingress 等,A 服务可能依赖 B 服务,B 服务还有可能依赖 C 服务等。注意,每一条链路都有可能配置重试,那么客户端的一次重试请求, C 服务可能会收到多个请求(甚至数十个)。可以看到,这存在明显的请求放大情况,极端情况下,C 服务需要承载可能被放大了数十倍。

        看到了吧,不合理的重试在某些情况下可能会导致非常严重的影响,一定要考虑哪些情况可以重试,哪些情况不能重试;另外在制定重试策略时,应该从全局去分析考虑,不能局限于局部的调用链路。


http://www.ppmy.cn/news/1516230.html

相关文章

Axios介绍;前后端分离开发的介绍;YAPI的使用;Vue项目简介、入门;Elementui的使用;nginx介绍

1 Ajax 1.1 Ajax介绍 1.1.1 Ajax概述 我们前端页面中的数据&#xff0c;如下图所示的表格中的学生信息&#xff0c;应该来自于后台&#xff0c;那么我们的后台和前端是互不影响的2个程序&#xff0c;那么我们前端应该如何从后台获取数据呢&#xff1f;因为是2个程序&#xf…

机器学习在旅游业的革新之旅

机器学习在旅游业的革新之旅 随着科技的飞速发展&#xff0c;尤其是人工智能&#xff08;AI&#xff09;技术的广泛应用&#xff0c;各个行业都迎来了前所未有的变革。其中&#xff0c;旅游业作为全球经济的重要支柱之一&#xff0c;更是受益匪浅。机器学习&#xff08;Machin…

AWS SAM CLI 备忘单!

安装 AWS SAM CLI brew tap aws/tap brew 安装 aws-sam-cli 验证安装 $ sam --version 升级 SAM $ brew upgrade aws-sam-cli 您需要 AWS 凭证才能在 AWS 上工作。 构建并部署简单应用程序 $ sam init→ 下载示例应用程序 $ sam build→ 构建您的应用程序 $ sam deploy --guid…

绿色积分引领:我店平台的可持续消费革命

在当今数字化浪潮的推动下&#xff0c;“我店”凭借其创新的环保积分系统&#xff0c;在消费市场中脱颖而出&#xff0c;逐渐改变着市场的结构。本文将详细分析该平台的竞争优势、市场策略以及它如何利用创新手段塑造未来的消费趋势。 一、环保积分&#xff1a;消费体验革新的关…

永磁同步电机高性能控制算法(13)后续篇—— 基于高阶扩张状态观测器(ESO)的无模型预测控制(MFPC)

1.前言 前文已经介绍过了高阶ESO相对于传统ESO的优势。 https://zhuanlan.zhihu.com/p/703039702https://zhuanlan.zhihu.com/p/703039702 但是当时搭的ESO有点问题。把公式修正之后&#xff0c;发现前文用的改进四阶ESO无法使用。 今天来解释一下为什么改进4阶ESO无法使用…

SQL, 有终止条件的多次累计计算

MSSQL数据库的data表存储了多人上电梯的情况&#xff0c;turn表示进电梯的顺序。电梯最大承重1000公斤&#xff0c;每趟能上的人数有限&#xff0c;超重的人要等下一趟。nameweightturnAlice2501Bob1702Alex3503John4004Winston5005Marie2006 请计算每趟电梯最后一个进入的人的…

笔记整理—uboot启动过程(5)BL2板级初始化

上一章说到了uboot在BL2阶段大概都要干什么&#xff0c;也说到了为了实现这些要先进行内存排布&#xff0c;实现了这些后便可实现BL2部分的板级初始化。首先先来看一下init_fnc_ptr函数指针。 for(init_fnc_ptrinit_sequence;*init_fnc_ptr;init_fnc_ptr){if((*init_fnc_ptr)(…

gitlab迁移至新的服务器

第一步&#xff0c;查看旧服务器的gitlab版本&#xff0c;在新服务器上安装一个相同版本的 cat /opt/gitlab/embedded/service/gitlab-rails/VERSION wget https://mirrors.tuna.tsinghua.edu.cn/gitlab-ce/yum/el8/gitlab-ce-14.9.3-ce.0.el8.x86_64.rpm rpm -ivh gitlab-ce-1…

SSRF漏洞复现

目录 web-ssrfme ssrf攻击本地fastcgi漏洞复现 web-ssrfme 该漏洞需要部署在Linux下&#xff0c;拉取docker 映射到8091端口上&#xff0c;直接访问靶场ip的8091端口 进入题目&#xff0c;直接把源码给了&#xff0c;那我们分析源码&#xff0c;源码过滤了file协议、dict协…

WPS Office两个严重漏洞曝光,已被武器化且在野利用

WPS Office作为一款用户基数超过2亿的广泛使用的办公套件&#xff0c;被发现存在两个关键漏洞&#xff08;CVE-2024-7262和CVE-2024-7263&#xff09;&#xff0c;这些漏洞可能导致用户遭受远程代码执行攻击。这两个漏洞的CVSS评分为9.3&#xff0c;表明它们的严重性很高&#…

安卓手机使用 Google Play 谷歌应用商店安装APP一直转圈等待

如果去国外旅游&#xff0c;可能需要安装一些当地的 APP 比如打车软件。 出发之前&#xff0c;在国内先把 APP 安装好。 首先&#xff0c;你要科学上网&#xff0c;才能在 Google play 里面搜索 APP。 然后&#xff0c;点安装&#xff0c;然后&#xff0c;就看到一直转圈&am…

SSRF以及CSRF

ssrf 服务端请求伪造&#xff1a;由于服务端提供了从其他服务器应用获取数据的功能&#xff0c;但又没有对目标地址做严格过滤与限制&#xff0c;导致攻击者可以传入任意的地址来让后端服务器对其发起请求&#xff0c;并返回对该目标地址请求的数据 数据流&#xff1a;攻击者…

[数据集][目标检测]起子检测数据集VOC+YOLO格式1215张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;1215 标注数量(xml文件个数)&#xff1a;1215 标注数量(txt文件个数)&#xff1a;1215 标注…

Docker 安装与配置 Docker Registry 指南

一、安装 Docker 解压docker.tar文件&#xff1a; rootiZbp1h35mcqj4eppj2bo1rZ:/data/dw# tar xf docker.tar解压后检查当前目录&#xff0c;发现解压出一个名为 docker_install 的目录。 进入解压出的目录并查看内容&#xff1a; rootiZbp1h35mcqj4eppj2bo1rZ:/data/dw# cd …

SQL Server数据库查询常用语句汇总

这里&#xff0c;汇总了在使用SQL Server数据库的过程中经常会写的查询语句。 情形1 根据时间查询最新一条数据 &#xff08;dtime类型为datetime&#xff09; select top 1 名称 as name,列名1 as parname1,列名2 as parname2,dtime,col1,col2 from demo order by dtime …

‌前端列表展示1000条大量数据时,后端通常需要进行一定的处理。‌

‌前端列表展示1000条数据时&#xff0c;后端通常需要进行一定的处理。‌ 在处理大量数据时&#xff0c;后端和前端需要协同工作&#xff0c;以确保数据的正确展示和性能优化。后端主要负责数据处理和逻辑运算&#xff0c;而前端则负责数据的展示和用户交互。对于大量数据的展…

CM工作室发展史 上

&#xff0c;注&#xff1a;本文章未使用"无标题技术" 目录 &#xff08;超长文章&#xff01;&#xff09; 新手时期 初来乍到 第一篇文章 第一个专栏——沙雕程序 学习"块引用" 第一次修改用户名 学习"代码" "头文件风波"时期 头…

SpringBoot工厂模式

前言 下面的示例展示了 SpringBoot 中如何使用工厂模式&#xff0c;该示例通过 ApplicationContext 直接获取 Spring 容器中所有 Animal 的 Bean&#xff0c;然后将它们存储在 animalMap 中&#xff0c;使用时直接从 Map 中获取实例。 另一种工厂模式可参考我另一篇文章 &…

实现Nginx四层负载均衡

Nginx在1.9.0版本开始支持tcp模式的负载均衡&#xff0c;在1.9.13版本开始支持udp协议的负载&#xff0c;udp主要用于 DNS的域名解析&#xff0c;其配置方式和指令和http 代理类似&#xff0c;其基于ngx_stream_proxy_module模块实现tcp 负载&#xff0c;另外基于模块ngx_strea…

零基础5分钟上手亚马逊云科技核心云架构知识-创建NoSQL数据库

简介&#xff1a; 欢迎来到小李哥全新亚马逊云科技AWS云计算知识学习系列&#xff0c;适用于任何无云计算或者亚马逊云科技技术背景的开发者&#xff0c;通过这篇文章大家零基础5分钟就能完全学会亚马逊云科技一个经典的服务开发架构方案。 我会每天介绍一个基于亚马逊云科技…