一文搞懂微服务架构之限流

前置知识

限流是通过限制住流量大小来保护系统,能够解决异常突发流量打崩系统的问题。例如常见的某个攻击者在攻击你维护的系统,那么限流就是极大程度上保护住你的系统。

算法

限流算法也可以像负载均衡算法那样,划分成静态算法和动态算法两类。

  • 静态算法包括令牌桶、漏桶、固定窗口和滑动窗口。这些算法就是要求研发人员提前设置好阈值。在算法运行期间不会关注服务器的真实负载。
  • 动态算法也叫做自适应限流算法,典型的是BBR算法,利用一系列指标判断是否应该减少流量或放大流量。动态算法和TCP的拥塞控制是非常接近的,只不过TCP控制的是报文流量,而微服务控制的是请求流量。

也可以参考熔断和降级里面的思路,选用一些指标来设计自己的限流算法。例如你的业务需要很多内存,可以根据剩余空闲内存来判断要不要限流。

令牌桶

系统会以一个恒定的速率产生令牌,这些令牌会放到一个桶里面,每个请求只有拿到了令牌才会被执行。每当一个请求过来的时候,就需要尝试从桶里面拿一个令牌。如果拿到了令牌,那么请求就会被处理掉;如果没有拿到,那么这请求就被限流了。
在这里插入图片描述

本身令牌桶是可以积攒一定数量的令牌的,比如桶的容量是100,也就是这里面最多积攒100个令牌。那么当某一时刻突然来了100个请求,它们都能拿到令牌

漏桶

当请求不均匀的速度到达服务器之后,限流器会以固定的速率转交给业务逻辑
在这里插入图片描述
某种程度上,可以把漏桶算法看作令牌桶算法的一种特殊形态。将令牌桶中桶的容量设想为0,就是漏桶了。
在这里插入图片描述
所以你可以看到,在漏桶里面,令牌产生之后你就需要取走,没取走的话也不会积攒下来。因此漏桶是绝对均匀的,而令牌桶不是绝对均匀的。

固定窗口与滑动窗口

在这里插入图片描述
固定窗口是指在一个固定时间段,只允许执行固定数量的请求。比如一秒钟之内只能执行100个请求。
滑动窗口类似固定窗口,也是指一个固定时间段里,只允许执行固定数量的请求,区别在于,滑动窗口是平滑地挪动窗口,而不是像固定窗口那样突然地挪走窗口。
假设窗口大小是一分钟,此时时间是t1,那么窗口地起始位置是t1-1分钟。过了2秒以后,窗口大小是1分钟,但是窗口地起始位置也向后挪动了2秒,变成了t1-1分钟+2秒。

限流对象

针对什么来进行限流。

从单机和集群的角度来看,可以分为单机限流或者集群限流。集群限流一般需要借助Redis之类的中间件来记录流量和阈值,也就是需要用Redis等工具来实现前面的限流算法。当然如果利用网关来实现集群限流,可以解决Redis。
在这里插入图片描述

针对业务对象限流

  • VIP用户不限流而普通用户限流
  • 针对IP限流。用户登录或参与秒杀都可以使用这种限流,比如说设置一秒钟最多有50个请求。
  • 针对业务ID限流,比如用户ID

限流后的做法

即使一个请求被限流了,也可以设置一些精巧的方案来处理。

  • 同步阻塞等待一段时间。如果是偶发性的触发了限流,那么稍微阻塞等待一会,后面有极大概率能得到处理。比如限流设置为一秒钟100个请求,恰好来了101个请求,多出来的一个请求只需要等待一秒钟,下一秒钟就会被处理。但是要注意控制超时
    在这里插入图片描述
  • 同步转异步:如果一个请求没被限流,就直接同步处理;否则,那么这个请求就会被存储起来,等到业务低峰期的时候再处理,其实和降级差不多。
  • 调整负载均衡算法:如果某个请求限流了,相当于告诉负载均衡器,应该尽可能少的给这个节点发送请求。在熔断里讲过类似的方案,不过熔断里是负载均衡器后续不再发请求,而在限流这里还是会发送请求,只是降低转发到该节点的概率,通过调整节点的权重就能达到这种效果。
    在这里插入图片描述

面试算法

理论上,要能够说出各种算法的基本原理,动态算法的BBR可以先不看。
漏桶、令牌桶、滑动窗口和固定窗口这几个算法要能写出来。
了解公司使用限流的情况,正常来说,核心HTTP请求和核心服务都应该使用限流来保障系统的可用性。对于每一个限流,都要了解这些

  • 限流的阈值是多少?为什么限定这个阈值?
  • 被限流的请求会怎么处理,直接拒绝还是阻塞到超时还是转异步处理?

面试限流的最好策略就是为自己打造一个掌握了高可用微服务架构的人,限流就是提高系统可用性时的一个具体策略。

  • 讨论对外的API,如HTTP接口或公共API时,可以强调使用限流来保护系统
  • 讨论TCP拥塞控制时,可以提起服务治理上限流也借鉴了TCP拥塞控制
  • 讨论Redis或类似产品时,可以提Redis实现过集群限流

基本思路

先阐述限流的总体目标,然后回答前置知识的三个点:算法、限流对象和限流后的做法,最后再把话题引到计算阈值上。

限流是为了保证系统可用性,防止系统因为流量过大而崩溃的一种服务治理手段。从算法上来说,有令牌桶、漏桶、固定窗口和滑动窗口算法。还有动态限流算法,或者说自适应限流算法,比较有名的就是参考了 TCP 拥塞控制算法 BBR 衍生出来的算法,比如说 B 站开源的 Kratos 框架就有一个实现。这些算法之间比较重要的一个区别是能否处理小规模的突发流量
从限流对象上来说,可以是集群限流或者单机限流,也可以是针对具体业务来做限流。比如说在登录的时候,我们经常针对 IP 进行限流。又或者在一些增值服务里面,非付费用户也会被限流。
触发限流之后,具体的措施也可以非常灵活。被限流的请求可以同步阻塞一段时间,也可以考虑同步转异步。如果负载均衡算法灵活的话,也可以做一些调整,减少发到该节点的概率。
用好限流的一个重要前提是能够设置准确的阈值,例如每秒钟限制在 100 个请求还是限制在 200 个请求。如果阈值过低,那么系统资源就容易闲置浪费;如果阈值太高,那么系统可能撑不住那么多流量,导致崩溃。

同时你还要补充一个简单的例子,关键词是 IP 限流。你也可以考虑使用你的真实案例。

我在我们公司的登录接口里面就引入了限流机制。正常情况下,一个用户在一秒钟内最多点击一次登录,所以针对每一个 IP,我限制它最多只能在一秒内提交 50 次登录请求。这个 50 充分考虑到了公共 IP 的问题,正常用户是不可能触发这个阈值的。这个限流虽然很简单,但是能够有效防范一些攻击。不过限流再怎么防范,还是会出现系统撑不住流量的情况。

在这里插入图片描述
面试官接下来大概会问每一个算法、不同的限流对象,以及限流后的不同做法的细节。这部分你按照前置知识里面的内容来回答就可以

突发流量

假如说正常你的限流是一秒钟 100 个请求,但是如果某一秒钟来了 101 个请求,你依旧会觉得第 101 个请求应该尽可能处理掉。在这种场景下,漏桶是做不到的,因为漏桶是非常均匀的。一秒钟 100 个请求在漏桶里面就是 10 毫秒一个请求,绝对不会多也不会少。
而令牌桶就能够处理。比如说令牌桶产生令牌的速率是 100 个每秒,但是桶的容量是 20 个,那么也就是说某一秒钟内,最多可以处理 120 个请求。
在这里插入图片描述
固定窗口和滑动窗口有一个类似的问题,就是毛刺问题。
假如一个窗口大小是一分钟 1000 个请求,你预计这 1000 个请求会均匀分散在这一分钟内。那么有没有可能第一秒钟就来了 1000 个请求?当然可能。那当下这一秒系统有没有可能崩溃?自然也是可能的。
在这里插入图片描述
所以固定窗口和滑动窗口的窗口时间不能太长。比如说以秒为单位是合适的,但是以分钟作为单位就是不合适的。那么在面试官问到,或者你在介绍了漏桶或令牌桶算法之后,就可以补充这一段。

漏桶算法非常均匀,但是令牌桶相比之下就没那么均匀。令牌桶本身允许积攒一部分令牌,所以如果有偶发的突发流量,那么这一部分请求也能得到正常处理。但是要小心令牌桶的容量,不能设置太大。不然积攒的令牌太多的话就起不到限流效果了。例如容量设置为 1000,那么要是积攒了 1000 个令牌之后真的突然来了 1000 个请求,它们都能拿到令牌,那么系统可能撑不住这突如其来的 1000 个请求。

请求大小

刚刚的讨论都是针对请求的个数进行的,但是没有考虑到请求的大小。

限流是针对请求个数进行的,那么显然,如果有两台实例,一台实例处理的都是小请求,另一台实例处理的都是大请求,那么都限流在每秒 100 个请求。可能第一台实例什么问题都没有,而第二台实例就崩溃了。
所以如果面试官问到为什么使用了限流,系统还是有可能崩溃,或者你在负载均衡里面聊到了请求大小的问题,都可以这样来回答,关键词是请求大小

限流和负载均衡有点儿像,基本没有考虑请求的资源消耗问题。所以负载均衡不管怎么样,都会有偶发性负载不均衡的问题,限流也是如此。例如即便我将一个实例限制在每秒 100 个请求,但是万一这个 100 个请求都是消耗资源很多的请求,那么最终这个实例也可能会承受不住负载而崩溃。动态限流算法一定程度上能够缓解这个问题,但是也无法根治,因为一个请求只有到它被执行的时候,我们才知道它是不是大请求。

计算阈值

总体的思路:看服务的观测数据、压测、借鉴、手动计算

看服务的性能数据属于常规解法,基本就是看业务高峰期的QPS来确定整个集群的阈值。如果确定单机的阈值,再除以实例个数,所以可以这样来回答,关键词是业务性能数据

我们公司有完善的监控,所以我可以通过观测到的性能数据来确定阈值。比如说观察线上的数据,如果在业务高峰期整个集群的 QPS 都没超过 1000,那么就可以考虑将阈值设定在 1200,多出来的 200 就是余量。 不过这种方式有一个要求,就是服务必须先上线,有了线上的观测数据才能确定阈值。并且,整个阈值很有可能是偏低的。因为业务巅峰并不意味着是集群性能的瓶颈。如果集群本身可以承受每秒 3000 个请求,但是因为业务量不够,每秒只有 1000 个请求,那么我这里预估出来的阈值是显著低于集群真实瓶颈 QPS 的。

不过我个人觉得,最好的方式应该是在线上执行全链路压测,测试出瓶颈。即便不能做全链路压测,也可以考虑模拟线上环境进行压测,再差也应该在测试环境做一个压力测试。

做压测,而且你要强调全链路压测。理由很简单,限流针对的是线上环境,那么自然要尽可能模拟线上环境。最符合这个要求的就是全链路压测了,它就是直接在线上环境执行的,因此结果也是最准的。然后你需要进一步解释,怎么利用压测结果。大部分性能测试的结果类似于图片里展示的这样,当然你是不太可能搞出来那么优雅的图形,多少会有些偏差。

在这里插入图片描述
理论上来说,你可以选择 A、B、C 当中的任何一个点作为你的限流的阈值。
A 是性能最好的点。A 之前 QPS 虽然在上升,但是响应时间稳定不变。在这个时候资源利用率也在提升,所以选择 A 你可以得到最好的性能和较高的资源利用率。
B 是系统快要崩溃的临界点。很多人会选择这个点作为限流的阈值。这个点响应时间已经比较长了,但是系统还能撑住。选择这个点意味着能撑住更高的并发,但是性能不是最好的,吞吐量也不是最高的。
C 是吞吐量最高的点。实际上,有些时候你压测出来的 B 和 C 可能对应到同一个 QPS 的值。选择这个点作为限流阈值,你可以得到最好的吞吐量。
你在回答怎么选之前,最好给面试官比划一下上面这张图中的三条曲线,然后解释这三个点,口诀就是性能 A、并发 B、吞吐量 C

综合来说,如果是性能苛刻的服务,我会选择 A 点。如果是追求最高并发的服务,我会选择 B 点,如果是追求吞吐量的服务,我会选择 C 点。

面试官多半会杠你,压力测试特别难,或者有些服务根本测不了,那你怎么办。这个时候,你需要说点正确但没用的废话,关键词压测是基操。你在表述的时候语气要委婉,态度要坚决。

一般我会认为一家公司应该把压测作为提高系统性能和可用性的一个关键措施,毕竟没有压测数据,性能优化和可用性改进也不知道怎么下手。所以我还是比较建议尽可能把压测搞起来,反正压测这个东西是迟早要有的。
然后你就要转过话头,顺着面试官的话往下说,讨论真的做不了压测的时候怎么确定阈值。关键词就是借鉴。
不过如果真的做不了,或者来不及,或者没资源,那么还可以考虑参考类似服务的阈值。比如说如果 A、B 服务是紧密相关的,也就是通常调用了 A 服务就会调用 B 服务,那么可以用 A 已经确定的阈值作为 B 的阈值。又或者 A 服务到 B 服务之间有一个转化关系。比如说创建订单到支付,会有一个转化率,假如说是 90%,如果创建订单的接口阈值是 100,那么支付的接口就可以设置为 90。

这个时候面试官可能会继续问:如果我这是一个全新的业务呢?也就是说,你都没得借鉴。这个时候就只剩下最后一招了—— 手动计算。

实在没办法了,就只能手动计算了。也就是沿着整条调用链路统计出现了多少次数据库查询、多少次微服务调用、多少次第三方中间件访问,如 Redis,Kafka 等。举一个最简单的例子,假如说一个非常简单的服务,整个链路只有一次数据库查询,这是一个会回表的数据库查询,根据公司的平均数据这一次查询会耗时 10ms,那么再增加 10 ms 作为 CPU 计算耗时。也就是说这一个接口预期的响应时间是 20ms。如果一个实例是 4 核,那么就可以简单用 1000ms÷20ms×4=200 得到阈值

这个时候你还可以进一步补充一些手动计算要考虑的事情。

手动计算准确度是很差的。比如说垃圾回收类型语言,还要刨除垃圾回收的开销,相当于 200 打个折扣。折扣多大又取决于你的垃圾回收频率和消耗。
最好还是把阈值做成可以动态调整的。那么在最开始上线的时候就可以把阈值设置得比较小。后面通过观测发现系统还很健康,就可以继续上调阈值。

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

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

相关文章

【Java】—— Java面向对象高级:关键字static的使用

目录 1. 关键字:static 1.1 类属性、类方法的设计思想 1.2 static关键字 1.3 静态变量 1.3.1 语法格式 1.3.2 静态变量的特点 1.4 静态方法 1.4.1 语法格式 1.4.2 静态方法的特点 1.5 练习 1. 关键字:static 回顾类中的实例变量(即…

Android - Windows平台下Android Studio使用系统的代理

这应该是第一篇Android的博文吧。以后应该会陆续更新的。记录学习Android的点点滴滴。 之前也看过,不过看完书就忘了,现在重拾Android,记录学习历程。 为何要用代理 因为更新gradle太慢了。 如何使用系统的代理 先找到系统代理的ip和端口。…

C++学习笔记----6、内存管理(一)---- 使用动态内存(3)

3.2、对象数组 对象数组与原型/基础类型的数组没有什么不同,除了元素的初始化之外。当你使用new[N]去分配N个对象,就把N个连续的块空间分配出去了,每一个块空间可以放一个单独的对象。对于对象数组,New[]对每一个对象自动调用0参数…

激光雷达产品介绍

与传统激光雷达线性重复式的扫描方式不同,Livox mid系列激光雷达扫描路径不会重复。且视场中激光照射到的区域面积会随时间增大,这就意味着视场覆盖率随时间推移而显著提高。 内容参考自《解构大疆旗下 Livox Mid 激光雷达非重复扫描技术》作者&#xff…

【C++11(一)之入门基础)】

文章目录 C简介统一的列表初始化{}初始化 std::initializer_liststd::initializer_list是什么类型:std::initializer_list使用场景: 声明autodecltypenullptr STL中一些变化 C简介 在2003年C标准委员会曾经提交了一份技术勘误表(…

#ARM开发 笔记

课程介绍 ARM开发 --> Linux移植 --> 驱动开发 前后联系:ARM和系统移植为驱动开发学习做准备工作 所需知识:C语言基础及STM32需要的硬件知识 学习方法 学习流程、思想和解决问题的方法即可 知道驱动的基本框架以及基本开发要求 底层课程导学 接口技…

linux小程序-进度条

文章目录 pro.hpro.cmain.cmakefile测试 pro.h #pragma once#include <stdio.h>typedef void(*callback_t)(double, double);void probar(double total, double current);pro.c #include "pro.h" #include <string.h> #include <unistd.h> #defi…

webshell绕过样本初体验

目录 一&#xff1a;前景 二&#xff1a;样本 样本一&#xff1a; 样本二&#xff1a; 样本三&#xff1a; 样本4&#xff1a; 样本5&#xff1a; 一&#xff1a;前景 在我们日常的网站中百分之一百是存在一些安全设备来拦截我们的webshell的&#xff0c;一般情况…

Kafka大厂面试14问(附答案)

怎么保证顺序消费&#xff1f; 同一个生产者发送到同一分区的消息&#xff0c;先发送的比后发送的offset要小。同一生产者发送到不同分区的消息&#xff0c;消息顺序无法保证。 怎么解决这个问题&#xff1f; 给一个topic只设置一个分区 相同key会发给一个分区 怎么保证幂…

[有彩蛋]大模型独角兽阶跃星辰文生图模型Step-1X上线,效果具说很炸裂?快来看一手实测!

先简单介绍一下阶跃星辰吧 公司的创始人兼CEO是姜大昕博士&#xff0c;他在微软担任过全球副总裁&#xff0c;同时也是微软亚洲互联网工程研究院的副院长和首席科学家。 2024年3月&#xff0c;阶跃星辰发布了Step-2万亿参数MoE语言大模型预览版&#xff0c;这是国内初创公司首…

Centos7通过reposync搭建本地Yum源

目录 1. 服务端搭建 1.1. 安装相关软件包 1.2. 加载几个常用的yum源 1.3. 创建文件保存目录 1.4. 把各仓库同步到本地 1.5. 生成仓库信息 1.6. 定时任务更新仓库 1.7. nginx配置下载服务 1.8. 内网测试nginx服务配置是否正确 2. 客户端配置 前言&#xff1a;之前使用…

Nginx负载均衡数据流分析

1、各机器ip信息 客户端IP&#xff1a;192.168.3.239 Nginx代理服务器IP&#xff1a;192.168.3.241 服务端IP&#xff1a;192.168.3.238 2、架构图&#xff08;略&#xff09; 3、 下图是在服务端上面的抓包分析。 下图是在客户端上面的抓包分析&#xff1a; 下图是在代理服务…

动态路由和路由导航守卫及其案例分析

为什么需要动态路由&#xff1f; 动态路由其实用的不多&#xff0c;在实际开发中&#xff0c;如果遇到权限分配问题&#xff0c;比如对于一个公司人员的后台管理系统&#xff0c;那对不同成员的权限肯定不同&#xff0c;对于人事部&#xff0c;他们有权限进入成员表对人员的流…

PHP8、ThinkPHP8框架中间的应用教程详解

前言 虽然PHP的落幕的话题一直不绝&#xff0c;但是实际在WEB端项目中PHP占有率达到了70%以上&#xff0c;一直在WEB一枝独秀&#xff0c;它以快速、高效的开发闻名&#xff0c;出圈了几十年&#xff0c;等待只是下一次的涅槃。而经过PHP8、PHP9的演变发展&#xff0c;PHP逐渐…

【Linux网络编程】协议|OSI模型|TCP/IP模型|局域网通信|跨网络通信|地址管理|流程图

目录 ​编辑 一&#xff0c;协议 协议分层 二&#xff0c;OSI七层模型 三&#xff0c;TCP/IP五层&#xff08;或四层&#xff09;模型 TCP/IP各个层次一些名词解释 为什么要有TCP/IP协议 TCP/IP协议栈与操作系统的宏观关系示意图 四&#xff0c;网络传输基本流程 局…

【书生大模型实战营】MindSearch CPU-only 版部署

MindSearch CPU-only 版部署 MindSearch CPU-only 版部署任务步骤 MindSearch CPU-only 版部署 任务 将 MindSearch 部署到 HuggingFace 并美化 Gradio 的界面&#xff0c;并提供截图和 Hugging Face 的Space的链接。 步骤 按照官方教程&#xff0c;实现在网页上打开MindSe…

llama_factory Qlora微调异常 No package metadata was found for The ‘autoawq‘

importlib.metadata.PackageNotFoundError: No package metadata was found for The ‘autoawq’ distribution was not found and is required by this application. To fix: pip install autoawq 其实问题比较简单 直接安装autoawq 即可 但是对应会有版本问题&#xff1a; 查…

Python自适应光学模态星形小波分析和像差算法

&#x1f3af;要点 &#x1f3af;星形小波分析像差测量 | &#x1f3af;对比傅里叶和小波分析 | &#x1f3af;定义多尺度图像质量度量&#xff0c;矩阵数据 | &#x1f3af;像差校正算法 | &#x1f3af;受激发射损耗显微镜布局 | &#x1f3af;干涉仪分支校准&#xff0c;求…

【unity实战】使用新版输入系统Input System+Rigidbody实现第三人称人物控制器(附项目源码)

最终效果 前言 使用CharacterController实现3d角色控制器&#xff0c;之前已经做过很多了&#xff1a; 【unity小技巧】unity最完美的CharacterController 3d角色控制器&#xff0c;实现移动、跳跃、下蹲、奔跑、上下坡、物理碰撞效果&#xff0c;复制粘贴即用 【unity实战】C…

快速入门Go:Go + gin + MongoDB

Go 进阶:Go + gin + MongDB 极速搭建EcommerceSys电商系统 前言 本章节适合有一定基础的 Golang 初学者,通过简单的项目实践来加深对 Golang 的基本语法和 Web 开发的理解。 本文章持续更新中,请关注… 项目结构 项目流程图 技术栈(待补充)项目结构项目路由 (待补充) …