热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

微服务可用性设计(二):过载保护,限流

微服务可用性设计(一):隔离,超时过载保护令牌桶算法是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。令牌桶算法的描述如下:假设限制2rs,则按照500毫秒的固定速率往桶中添



微服务可用性设计(一):隔离,超时


过载保护


令牌桶算法

是一个存放固定容量令牌的桶,按照固定速率往桶里添加令牌。令牌桶算法的描述如下:


  • 假设限制2r/s,则按照500毫秒的固定速率往桶中添加令牌。
  • 桶中最多存放 b 个令牌,当桶满时,新添加的令牌被丢弃或拒绝。
  • 当一个 n 个字节大小的数据包到达,将从桶中删除n 个令牌,接着数据包被发送到网络上。
  • 如果桶中的令牌不足 n 个,则不会删除令牌,且该数据包将被限流(要么丢弃,要么缓冲区等待)。

token-bucket rate limit algorithm: /x/time/rate


令牌桶流入速度固定,允许请求激增。单机部署就可以实现稳定的微服务限流


漏桶算法

作为计量工具(The Leaky Bucket Algorithm as a Meter)时,可以用于流量整形(Traffic Shaping)和流量控制(TrafficPolicing),漏桶算法的描述如下:


  • 一个固定容量的漏桶,按照常量固定速率流出水滴。
  • 如果桶是空的,则不需流出水滴。
  • 可以以任意速率流入水滴到漏桶。
  • 如果流入水滴超出了桶的容量,则流入的水滴溢出了(被丢弃),而漏桶容量是不变的。
    leaky-bucket rate limit algorithm: /go.uber.org/ratelimit

单机版可以实现稳定的微服务限流

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


  • -集群增加机器或者减少机器限流阈值是否要重新设置?
  • 设置限流阈值的依据是什么?
  • 人力运维成本是否过高?
  • 当调用方反馈429时, 这个时候重新设置限流, 其实流量高峰已经过了重新评估限流是否有意义?

这些其实都是采用漏斗桶/令牌桶的缺点, 总体来说就是太被动, 不能快速适应流量变化。
因此我们需要一种自适应的限流算法,即: 过载保护,根据系统当前的负载自动丢弃流量。

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


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

  • 在系统稳定的前提下,保持系统的吞吐量。
    常见做法:利特尔法则
    CPU、内存作为信号量进行节流(注意在内存激增时,会出发GC)。

  • 队列管理: 队列长度、LIFO。

  • 可控延迟算法: CoDel。



如何计算接近峰值时的系统吞吐?


  • CPU: 使用一个独立的线程采样,每隔 250ms 触发一次。在计算均值时,使用了简单滑动平均去除峰值的影响。
  • Inflight: 当前服务中正在进行的请求的数量。
  • Pass&RT: 最近5s,pass 为每100ms采样窗口内成功请求的数量,rt 为单个采样窗口中平均响应时间。



限流

限流是指在一段时间内,定义某个客户或应用可以接收或处理多少个请求的技术。例如,通过限流,你可以过滤掉产生流量峰值的客户和微服务,或者可以确保你的应用程序在自动扩展(Auto Scaling)失效前都不会出现过载的情况。


  • 令牌桶、漏桶 针对单个节点,无法分布式限流。
  • QPS 限流
    • 不同的请求可能需要数量迥异的资源来处理。
    • 某种静态 QPS 限流不是特别准。
  • 给每个用户设置限制
    • 全局过载发生时候,针对某些“异常”进行控制。
    • 一定程度的“超卖”配额。
  • 按照优先级丢弃。
  • 拒绝请求也需要成本。


分布式限流

分布式限流,是为了控制某个应用全局的流量,而非真对单个节点纬度。


  • 单个大流量的接口,使用 redis 容易产生热点。
  • pre-request 模式对性能有一定影响,高频的网络往返。
    思考:
  • 从获取单个 quota 升级成批量 quota。quota: 表示速率,获取后使用令牌桶算法来限制。


  • 每次心跳后,异步批量获取 quota,可以大大减少请求 redis 的频次,获取完以后本地消费,基于令牌桶拦截。
  • 每次申请的配额需要手动设定静态值略欠灵活,比如每次要20,还是50。

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

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

在这里插入图片描述

思考:


  • 我们经常面临给一组用户划分稀有资源的问题,他们都享有等价的权利来获取资源,但是其中一些用户实际上只需要比其他用户少的资源。

那么我们如何来分配资源呢?一种在实际中广泛使用的分享技术称作“最大最小公平分享”(Max-Min Fairness)。

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

最大最小公平分配算法的形式化定义如下:


  • 资源按照需求递增的顺序进行分配。
  • 不存在用户得到的资源超过自己的需求。
  • 未得到满足的用户等价的分享资源。

在这里插入图片描述


重要性

每个接口配置阈值,运营工作繁重,最简单的我们配置服务级别 quota,更细粒度的,我们可以根据不同重要性设定 quota,我们引入了重要性(criticality):


  • 最重要 CRITICAL_PLUS,为最终的要求预留的类型,拒绝这些请求会造成非常严重的用户可见的问题。
  • 重要 CRITICAL,生产任务发出的默认请求类型。拒绝这些请求也会造成用户可见的问题。但是可能没那么严重。
  • 可丢弃的 SHEDDABLE_PLUS 这些流量可以容忍某种程度的不可用性。这是批量任务发出的请求的默认值。这些请求通常可以过几分钟、几小时后重试。
  • 可丢弃的 SHEDDABLE 这些流量可能会经常遇到部分不可用情况,偶尔会完全不可用。

gRPC 系统之间,需要自动传递重要性信息。如果后端接受到请求 A,在处理过程中发出了请求 B 和 C 给其他后端,请求 B 和 C 会使用与 A 相同的重要性属性。


  • 全局配额不足时,优先拒绝低优先级的。
  • 全局配额,可以按照重要性分别设置。
  • 过载保护时,低优先级的请求先被拒绝。

熔断

断路器(Circuit Breakers): 为了限制操作的持续时间,我们可以使用超时,超时可以防止挂起操作并保证系统可以响应。因为我们处于高度动态的环境中,几乎不可能确定在每种情况下都能正常工作的准确的时间限制。断路器以现实世界的电子元件命名,因为它们的行为是都是相同的。断路器在分布式系统中非常有用,因为重复的故障可能会导致雪球效应,并使整个系统崩溃。


  • 服务依赖的资源出现大量错误。
  • 某个用户超过资源配额时,后端任务会快速拒绝请求,返回“配额不足”的错误,但是拒绝回复仍然会消耗一定资源。有可能后端忙着不停发送拒绝请求,导致过载。

但一刀切的形式太过暴力,用户的请求失败率太高。


自适应保护的熔断

Google SRE中有这样一种是算法:
p = max(0, (requests - K*accepts) / (requests + 1))
p代表被丢掉流量的概率
K越小代表熔断越激进(K=2是默认值)
当request趋近于正无穷,那么这个公式的结果极限趋近1


这种方式实现了在系统允许的情况下,尽可能放多的流量进来,而不是全部拒绝。相对一刀切的情况,用户请求成功率会高很多。



客户端流控

positive feedback: 用户总是积极重试,访问一个不可达的服务。


  • 客户端需要限制请求频次,retry backoff 做一定的请求退让。
  • 可以通过接口级别的error_details,挂载到每个 API 返回的响应里。




Gutter

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

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



Case Study


  • 二层缓存穿透、大量回源导致的核心服务故障。
  • 异常客户端引起的服务故障(query of death)
    • 请求放大。
    • 资源数放大。
  • 用户重试导致的大面积故障。



推荐阅读
  • 一、Hadoop来历Hadoop的思想来源于Google在做搜索引擎的时候出现一个很大的问题就是这么多网页我如何才能以最快的速度来搜索到,由于这个问题Google发明 ... [详细]
  • 云原生边缘计算之KubeEdge简介及功能特点
    本文介绍了云原生边缘计算中的KubeEdge系统,该系统是一个开源系统,用于将容器化应用程序编排功能扩展到Edge的主机。它基于Kubernetes构建,并为网络应用程序提供基础架构支持。同时,KubeEdge具有离线模式、基于Kubernetes的节点、群集、应用程序和设备管理、资源优化等特点。此外,KubeEdge还支持跨平台工作,在私有、公共和混合云中都可以运行。同时,KubeEdge还提供数据管理和数据分析管道引擎的支持。最后,本文还介绍了KubeEdge系统生成证书的方法。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
  • Java 11相对于Java 8,OptaPlanner性能提升有多大?
    本文通过基准测试比较了Java 11和Java 8对OptaPlanner的性能提升。测试结果表明,在相同的硬件环境下,Java 11相对于Java 8在垃圾回收方面表现更好,从而提升了OptaPlanner的性能。 ... [详细]
  • Sleuth+zipkin链路追踪SpringCloud微服务的解决方案
    在庞大的微服务群中,随着业务扩展,微服务个数增多,系统调用链路复杂化。Sleuth+zipkin是解决SpringCloud微服务定位和追踪的方案。通过TraceId将不同服务调用的日志串联起来,实现请求链路跟踪。通过Feign调用和Request传递TraceId,将整个调用链路的服务日志归组合并,提供定位和追踪的功能。 ... [详细]
  • 2021最新总结网易/腾讯/CVTE/字节面经分享(附答案解析)
    本文分享作者在2021年面试网易、腾讯、CVTE和字节等大型互联网企业的经历和问题,包括稳定性设计、数据库优化、分布式锁的设计等内容。同时提供了大厂最新面试真题笔记,并附带答案解析。 ... [详细]
  • 玩转直播系列之消息模块演进(3)
    一、背景即时消息(IM)系统是直播系统重要的组成部分,一个稳定的,有容错的,灵活的,支持高并发的消息模块是影响直播系统用户体验的重要因素。IM长连接服务在直播系统有发挥着举足轻重的 ... [详细]
  • 有意向可以发简历到邮箱内推.简历直达组内Leader.能做同事的话,内推奖励全给你. ... [详细]
  • 讨伐Java多线程与高并发——MQ篇
    本文是学习Java多线程与高并发知识时做的笔记。这部分内容比较多,按照内容分为5个部分:多线程基础篇JUC篇同步容器和并发容器篇线程池篇MQ篇本篇 ... [详细]
  • 2019我的金三银四
    先讲一下自己的情况吧,二本学生,17年毕业,目前在一家跨境电商从事Java技术开发工作(不是阿里,没那么厉害),技术栈目前偏向于容器云、持续集成持续交付这一块,也就是SpringBoot、Kuber ... [详细]
  • 技术方案:Spark、kafka、opentsdb、Yahoo的egads模型静态训练:采用两种算法进行模型的训练:指数移动平均和HotWinters,模型一天训练一次,即每天0点开始训练, ... [详细]
  • 微服务之总体架构篇
    一、单体架构存在的问题缺点:1、难以维护:当单体应用业务不断迭代后代码量非常臃肿,模整个项目非常复杂,每次更改代码都可能带来新的bug;2、部署项目麻烦:庞大之后项目部署效率 ... [详细]
  • 下图|通用型_企业用户如何选择合适的云服务器配置?
    篇首语:本文由编程笔记#小编为大家整理,主要介绍了企业用户如何选择合适的云服务器配置?相关的知识,希望对你有一定的参考价值。随着网络飞速发展,企业上云已成为 ... [详细]
  • 目录摘要SQL的现在NoSQL,NotOnlySQL要分布式,也要SQL总结引用摘要毫不夸张的说,关系数据库是企业软件系统的核心,企业形形色色信息行为的背后,都有关系数据库的支撑。 ... [详细]
  • 你知道Kafka和Redis的各自优缺点吗?一文带你优化选择,不走弯路 ... [详细]
author-avatar
mobiledu2502861377
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有