过载保护

令牌桶算法

存放固定容量令牌的桶,按照固定速率往桶里添加令牌

https://pkg.go.dev/golang.org/x/time/rate

漏桶算法

作为计量工具(The Leaky Bucket Algorithm as a Meter)时,可以用于流量整形(Traffic Shaping)和流量控制(TrafficPolicing)

https://pkg.go.dev/go.uber.org/ratelimit

令牌桶和漏桶有什么区别和本质原理

令牌桶可以接受突增流量进行处理,漏桶是固定速率进行请求,对于突增流量会被丢弃。

本质原理:

漏斗桶/令牌桶确实能够保护系统不被拖垮, 但不管漏斗桶还是令牌桶, 其防护思路都是设定一个指标, 当超过该指标后就阻止或减少流量的继续进入,当系统负载降低到某一水平后则恢复流量的进入。但其通常都是被动的,其实际效果取决于限流阈值设置是否合理,但往往设置合理不是一件容易的事情

令牌桶和漏桶算法的缺点:太被动, 不能快速适应流量变化

集群增加机器或者减少机器限流阈值是否要重新设置?

设置限流阈值的依据是什么?

人力运维成本是否过高?

当调用方反馈429时, 这个时候重新设置限流, 其实流量高峰已经过了重新评估限流是否有意义?

自适应限流:根据系统当前的负载自动丢弃流量

计算系统临近过载时的峰值吞吐作为限流的阈值来进行流量控制,达到系统保护

服务器临近过载时,主动抛弃一定量的负载,目标是自保。

计算系统最大吞吐

利特尔法则

最大可以接受请求数量 = latency(处理时间) * 最大成功数量

CPU: 使用一个独立的线程采样,每隔 250ms 触发一次。在计算均值时,使用了简单滑动平均去除峰值的影响。

指数加权移动平均法(EWMA)

https://www.cnblogs.com/jiangxinyang/p/9705198.html

Inflight: 当前服务中正在进行的请求的数量。

Pass&RT: 最近5s,pass 为每100ms采样窗口内成功请求的数量,rt 为单个采样窗口中平均响应时间

使用 CPU 的滑动均值(CPU > 800)作为启发阈值,一旦触发进入到过载保护阶段,算法为:(pass* rt) < inflight

限流效果生效后,CPU 会在临界值(800)附近抖动,如果不使用冷却时间,那么一个短时间的 CPU 下降就可能导致大量请求被放行,严重时会打满 CPU。

在冷却时间后,重新判断阈值(CPU > 800 ),是否持续进入过载保护。

具体代码:

https://github.com/go-kratos/kratos/blob/v1.0.x/pkg/ratelimit/bbr/bbr.go

func (l *BBR) shouldDrop() bool {
if l.cpu() < l.conf.CPUThreshold {
prevDrop, _ := l.prevDrop.Load().(time.Duration)
if prevDrop == 0 {
return false
}
if time.Since(initTime)-prevDrop <= time.Second {
inFlight := atomic.LoadInt64(&l.inFlight)
return inFlight > 1 && inFlight > l.maxFlight()
}
l.prevDrop.Store(time.Duration(0))
return false
}
inFlight := atomic.LoadInt64(&l.inFlight)
drop := inFlight > 1 && inFlight > l.maxFlight()
if drop {
prevDrop, _ := l.prevDrop.Load().(time.Duration)
if prevDrop != 0 {
return drop
}
l.prevDrop.Store(time.Since(initTime))
}
return drop
} func (l *BBR) maxFlight() int64 {
return int64(math.Floor(float64(l.maxPASS()*l.minRT()*l.winBucketPerSec)/1000.0 + 0.5))
}

这里除以 1000 也是让我想了一会的

一个窗口是100ms,使用 最大窗口通过的 (请求数量 * 窗口最小耗时 * 窗口数量) 这等于 1s内 10个窗口的最大请求数量

请求数量 * 窗口最小耗时 = 一个窗口最大可以接受的请求数量

然后 * 窗口数量 / 1000 等于一个窗口内最大的 吞吐数量

限流

限流是指在一段时间内,定义某个客户或应用可以接收或处理多少个请求的技术。

通过限流,你可以过滤掉产生流量峰值的客户和微服务,或者可以确保你的应用程序在自动扩展(Auto Scaling)失效前都不会出现过载的情况

令牌桶、漏桶 针对单个节点,无法分布式限流

为什么需要分布式限流?

保护下游服务和自身不会被突增的流量打死,比如服务日常可以处理1w流量,增加到2w出发自保护,但是一下子到10w的话,下游服务db和rpc服务承担不住,直接挂了。

每次心跳后,异步批量获取 quota,可以大大减少请求 redis 的频次,获取完以后本地消费,基于令牌桶拦截

如何基于单个节点按需申请,并且避免出现不公平的现象?

初次使用默认值,一旦有过去历史窗口的数据,可以基于历史窗口数据进行 quota 请求

最大最小公平分享”(Max-Min Fairness)。

直观上,公平分享分配给每个用户想要的可以满足的最小需求,然后将没有使用的资源均匀的分配给需要‘大资源’的用户

熔断

断路器(Circuit Breakers)

服务依赖的资源出现大量错误

触发熔断以后很快很多请求都会失败,对用户影响比较大, 所以是想让部分失败,丢弃部分请求,不要一下子打死

Google SRE

max(0, (requests - K*accepts) / (requests + 1))

代码位置:

https://github.com/go-kratos/kratos/blob/v1.0.x/pkg/net/netutil/breaker/sre_breaker.go

func (b *sreBreaker) Allow() error {
success, total := b.summary()
k := b.k * float64(success)
if log.V(5) {
log.Info("breaker: request: %d, succee: %d, fail: %d", total, success, total-success)
}
// check overflow requests = K * success
if total < b.request || float64(total) < k {
if atomic.LoadInt32(&b.state) == StateOpen {
atomic.CompareAndSwapInt32(&b.state, StateOpen, StateClosed)
}
return nil
}
if atomic.LoadInt32(&b.state) == StateClosed {
atomic.CompareAndSwapInt32(&b.state, StateClosed, StateOpen)
}
dr := math.Max(0, (float64(total)-k)/float64(total+1))
drop := b.trueOnProba(dr)
if log.V(5) {
log.Info("breaker: drop ratio: %f, drop: %t", dr, drop)
}
if drop {
return ecode.ServiceUnavailable
}
return nil
}

限流 - 客户端流控 退让

https://github.com/go-kratos/kratos/blob/v1.0.x/pkg/net/netutil/backoff.go

限流-gutter

基于熔断的 gutter kafka ,用于接管自动修复系统运行过程中的负载,这样只需要付出10%的资源就能解决部分系统可用性问题。

经常使用 failover 的思路,但是完整的 failover 需要翻倍的机器资源,平常不接受流量时,资源浪费。高负载情况下接管流量又不一定完整能接住。所以这里核心利用熔断的思路,是把抛弃的流量转移到 gutter 集群,如果 gutter 也接受不住的流量,重新回抛到主集群,最大力度来接受。

总结

分布式限流

自适用保护自己

客户端的熔断

立体式的防御增加可用性

go 进阶训练营 微服务可用性(中)笔记的更多相关文章

  1. Chris Richardson微服务翻译:微服务架构中的服务发现

    Chris Richardson 微服务系列翻译全7篇链接: 微服务介绍 构建微服务之使用API网关 构建微服务之微服务架构的进程通讯 微服务架构中的服务发现(本文) 微服务之事件驱动的数据管理 微服 ...

  2. Java生鲜电商平台-SpringCloud微服务架构中分布式事务解决方案

    Java生鲜电商平台-SpringCloud微服务架构中分布式事务解决方案 说明:Java生鲜电商平台中由于采用了微服务架构进行业务的处理,买家,卖家,配送,销售,供应商等进行服务化,但是不可避免存在 ...

  3. Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理

    Java生鲜电商平台-SpringCloud微服务架构中核心要点和实现原理 说明:Java生鲜电商平台中,我们将进一步理解微服务架构的核心要点和实现原理,为读者的实践提供微服务的设计模式,以期让微服务 ...

  4. SpringCloud微服务框架复习笔记

    SpringCloud微服务框架复习笔记 什么是微服务架构? 微服务是一种软件开发技术,它提倡将单一应用程序划分成一组小的服务,服务之间互相协调.互相配合,为用户提供最终价值.每个服务运行在其独立的进 ...

  5. 微服务架构中API网关的角色

    [上海尚学堂的话]:本文主要讲述了Mashape的首席技术执行官Palladino对API网关的详细介绍,以及API网关在微服务中所起的作用,同时介绍了Mashape的一款开源API网关Kong. A ...

  6. 微服务架构中APIGateway原理

    背景 我们知道在微服务架构风格中,一个大应用被拆分成为了多个小的服务系统提供出来,这些小的系统他们可以自成体系,也就是说这些小系统可以拥有自己的数据库,框架甚至语言等,这些小系统通常以提供 Rest ...

  7. 认证鉴权与API权限控制在微服务架构中的设计与实现(四)

    引言: 本文系<认证鉴权与API权限控制在微服务架构中的设计与实现>系列的完结篇,前面三篇已经将认证鉴权与API权限控制的流程和主要细节讲解完.本文比较长,对这个系列进行收尾,主要内容包括 ...

  8. JWT如何在Spring Cloud微服务系统中在服务相互调时传递

    转载请标明出处: http://blog.csdn.net/forezp/article/details/78676036 本文出自方志朋的博客 在微服务系统中,为了保证微服务系统的安全,常常使用jw ...

  9. kratos微服务框架学习笔记一(kratos-demo)

    目录 kratos微服务框架学习笔记一(kratos-demo) kratos本体 demo kratos微服务框架学习笔记一(kratos-demo) 今年大部分时间飘过去了,没怎么更博和githu ...

  10. 【CHRIS RICHARDSON 微服务系列】微服务架构中的进程间通信-3

    编者的话 |本文来自 Nginx 官方博客,是微服务系列文章的第三篇,在第一篇文章中介绍了微服务架构模式,与单体模式进行了比较,并且讨论了使用微服务架构的优缺点.第二篇描述了采用微服务架构的应用客户端 ...

随机推荐

  1. Flask快速入门1

    因为新换了一个工作,项目使用了Flask框架技术,需要快速学习下,学过Django这个重量级的框架基础后,再去学习Flask框架相对还是容易的. 当然入门基础容易,要深入理解还是要慢慢花时间深耕练习使 ...

  2. openssl基础使用(密码学 linux)

    目录        实验原理        实验过程            一.对称加密                1.使用rc4加解密                2.使用AES加解密     ...

  3. Delphi MEMO 循环往上往下滚动

    // 循环往上滚动 if Memo1.Perform(EM_SCROLL,SB_LINEDOWN,0)=0 then begin Memo1.Perform(WM_VSCROLL,SB_TOP,0); ...

  4. Redis 高可用方案

    本文分享自天翼云开发者社区<Redis 高可用方案>,作者:芋泥麻薯 一.常见使用方式 Redis的几种常见使用方式包括: Redis单副本: • Redis多副本(主从): • Redi ...

  5. HashMap-线程不安全的原因

    前言 HashMap线程安全的问题,在各大面试中都会被问到,属于常考热点题目.虽然大部分读者都了解它不是线程安全的,但是再深入一些,问它为什么不是线程安全的,仔细说说原理,用图画出一种非线程安全的情况 ...

  6. deepseek+dify工作流实现代码审计

    一.登录dify,设置deepseek apikey 登录dify(https://cloud.dify.ai/signin) 设置deepseek apikey 二.创建dify工作流 添加工作流应 ...

  7. Unity Mask原理及自定义遮罩

    主要内容 StencilBuffer是什么? 自定义Shader来实现遮罩 Unity Mask的原理 1.什么是StencilBuffer GPU在渲染前会为每个像素点分配一个1字节(8位)大小的内 ...

  8. 使用Python建模量子隧穿

    引言 量子隧穿是量子力学中的一个非常有趣且令人神往的现象.在经典物理学中,我们通常认为粒子必须克服一个势垒才能通过它.但是,在量子力学中,粒子有时可以"穿越"一个势垒,即使它的能量 ...

  9. CyclicBarrier的await()方法底层原理

    一.定义 CyclicBarrier 的 await() 方法是其核心功能之一,用于让线程在屏障点等待,直到所有参与的线程都到达屏障后,才能继续执行. 其底层实现依赖于 AQS(AbstractQue ...

  10. 使用open-feign进行远程服务调用

    想要远程调用别的服务 1).引入open-feign包 2).编写一个接口,告诉SpringCloud这个接口是调用哪个远程的服务 a.声明接口的每一个方法都是调用哪个远程服务的那个请求 3).开启远 ...