草庐IT

关于服务限流这回事,总算整明白了

JAVA旭阳 2023-03-28 原文

​前言

随着现在微服务、分布式系统的发展,各个服务之间的相互调用越来越复杂。为了保证自身服务的稳定性与高可用,当面对超过自身服务能力的请求调用时,要做一定的限流措施。如同五一、国庆期间的旅游出行、景区爆满,游客限流。我们的服务面对诸如秒杀、大促、618、双十一以及可能的恶意攻击、爬虫等高并发、大流量的场景也需要做服务限流。

对超出服务处理能力之外的请求进行拦截,对访问服务的流量进行限制,这就是服务限流。接下来我们就好好谈谈服务限流这回事儿。

两种限流方式

常见的限流方式可以分为两类:基于请求限流和基于资源限流。

  1. 基于请求限流
基于请求限流指从外部访问的请求角度考虑限流,常见的方式有两种。

第一种是限制总量,也就是限制某个指标的累积上限,常见的是限制当前系统服务的用户总量,例如:某个直播间限制总用户数上限为100万,超过100万后新的用户无法进入;某个抢购活动商品数量只有100个,限制参与抢购的用户上限为1万个,1万以后的用户直接拒绝。

第二种是限制时间量,也就是限制一段时间内某个指标的上限,例如1分钟内只允许10000个用户访问;每秒请求峰值最高为10万。

优点:

  • 实现简单
缺点:

  • 实践中面临的主要问题是比较难以找到合适的阈值。例如系统设定了1分钟10000个用户,但实际上6000个用户的时候系统就扛不住了;或者达到1分钟10000用户后,其实系统压力还不大,但此时已经开始丢弃用户访问了。而且还要考虑硬件相关的因素,例如一台32核的机器和64核的机器处理能力差别很大,阈值是不同的。
应用:

  • 适用于业务功能比较简单的系统,例如负载均衡系统、网关系统、抢购系统等。
  1. 基于资源限流
基于请求限流是从系统外部考虑的,而基于资源限流是从系统内部考虑的,也就是找到系统内部影响性能的关键资源,对其使用上限进行限制。常见的内部资源包括连接数、文件句柄、线程数和请求队列等。比如CPU的占用率超过80%的时候就开始拒绝新的请求。

优点:

  • 有效地反映当前系统的压力,更好的进行限流
缺点:

  • 难以确定关键资源
  • 难以确定关键资源的阈值,需要在线上逐步调试,持续观察,直到找到合适的值。
应用:

  • 适用于具体的某个服务,比如订单系统、商品系统等。

四种限流算法

常见的限流算法有4种,它们的实现原理和优缺点各不相同,在实际设计的时候需要根据业务场景来选择。

  1. 固定时间窗
固定时间窗算法的实现原理是,统计固定时间周期内的请求量或者资源消耗量,超过限额就会启动限流,如下图所示:

优点:

  • 实现简单
缺点:

  • 存在临界点问题。例如上图中的红蓝两点只间隔了短短10秒,期间的请求数却已经达到200,超过了算法规定的限额(1分钟内处理100)。但是因为这些请求分别来自两个统计窗口,从单个窗口来看还没有超出限额,所以并不会启动限流,结果可能导致系统因为压力过大而挂掉。
  1. 滑动时间窗
为了解决临界点问题,滑动时间窗算法应运而生,它的实现原理是,两个统计周期部分重叠,从而避免短时间内的两个统计点分属不同的时间窗的情况,如下图所示:

优点:

  • 不存在临界点问题
缺点:

  • 相对于固定窗口,复杂度有所提升
  1. 漏桶算法
漏桶算法的实现原理是,将请求放入“桶”(消息队列等),业务处理单元(线程、进程和应用等)从桶里拿请求处理,桶满则丢弃新的请求,如下图所示:

优点:

  • 突发大量流量时丢弃的请求较少,因为漏桶本身有缓存请求的作用
缺点:

  • 可以平滑流量,但是无法解决流量突增的问题。
  • 桶大小动态调整比较困难,需要不断的尝试才能找到符合业务需求的最佳桶大小。
  • 无法精确控制流出速度,也就是业务的处理速度。
漏桶算法主要适用于瞬时高并发流量的场景(例如刚才提到的0点签到、整点秒杀等)。在短短几分钟内涌入大量请求时,为了更好的业务效果和用户体验,即使处理慢一些,也要做到尽量不丢弃用户请求。

  1. 令牌桶算法
令牌桶算法和漏桶算法的不同之处在于,桶中放入的不是请求,而是“令牌”,这个令牌就是业务处理前需要拿到的“许可证”。也就是说,当系统收到一个请求时,先要到令牌桶里面拿“令牌”,拿到令牌才能进一步处理,拿不到就要丢弃请求。

它的实现原理是如下图所示:

优点:

  • 通过控制放入令牌的速率,可以动态调整处理速率,实现更加灵活。
  • 可以平滑限流,同时可以容忍突发流量,因为桶里面可以累积一定数量的令牌,当突发流量过来的时候,桶里面有累积的令牌,此时的业务处理速度会超过令牌放入的速度。
缺点:

  • 突发大量流量的时候可能丢弃很多请求,因为令牌桶不能累积太多令牌。
  • 实现相对复杂。
令牌桶算法主要适用于两种典型的场景,一种是需要控制访问第三方服务的速度,防止把下游压垮,例如支付宝需要控制访问银行接口的速率;另一种是需要控制自己的处理速度,防止过载,例如压测结果显示系统最大处理TPS是100,那么就可以用令牌桶来限制最大的处理速度。

五种限流策略

  1. 服务拒绝
当请求流量达到限流阈值时,对多余的请求直接拒绝。

可通过设计实现对指定域名、IP、客户端、应用、用户等不同来源的请求进行拒绝。

  1. 延时处理
通过将多余的请求加入缓存队列或延时队列,来应对短期的流量突增,高峰期过后开始将堆积的请求流量逐渐处理。

  1. 请求分级(优先级)
对不同来源的请求设置优先级,先处理优先级更高的请求。如VIP客户、重要的业务应用(如交易服务优先级高于日志服务)。

  1. 动态限流
可以监控系统相关指标、评估系统压力,通过注册中心、配置中心等动态调整限流阈值。

  1. 监控预警&动态扩容
如果有优秀的服务监控系统与自动部署、发布系统,可以通过监控系统自动监测系统运行情况,对短期内服务压力暴增、流量大幅写入的情况进行邮件、短信等方式进行预警。

在满足特定条件下,可自动部署、发布相关服务,起到动态扩容的效果。

三个限流位置

  1. 接入层限流
可以通过Nginx、API路由网关等对域名或IP进行限流,同时可以拦截非法请求。

  1. 应用限流
每个服务可以有自己的单机或集群限流措施,也可以调用第三方的限流服务,比如阿里的Sentinel限流框架。

  1. 基础服务限流
也可以对基础服务层进行限流。

  • 数据库:限制数据库连接、限制读写速率
  • 消息队列:限制消费速率(消费量、消费线程)

总结

本文从宏观角度总结了服务限流的两种方式,三个可以限流的位置,四种常见的限流算法,五种限流的策略。最后再补充几句,合理的限流配置,需要了解系统的吞吐量,所以,限流一般需要结合容量规划和压测来进行。当外部请求接近或者达到系统的最大阈值时,触发限流,采取其他的手段进行降级,保护系统不被压垮。

参考:http://www.studyofnet.com/555653372.html

有关关于服务限流这回事,总算整明白了的更多相关文章

  1. ruby - 使用 ruby​​ 和 savon 的 SOAP 服务 - 2

    我正在尝试使用ruby​​和Savon来使用网络服务。测试服务为http://www.webservicex.net/WS/WSDetails.aspx?WSID=9&CATID=2require'rubygems'require'savon'client=Savon::Client.new"http://www.webservicex.net/stockquote.asmx?WSDL"client.get_quotedo|soap|soap.body={:symbol=>"AAPL"}end返回SOAP异常。检查soap信封,在我看来soap请求没有正确的命名空间。任何人都可以建议我

  2. ruby - 具有身份验证的私有(private) Ruby Gem 服务器 - 2

    我想安装一个带有一些身份验证的私有(private)Rubygem服务器。我希望能够使用公共(public)Ubuntu服务器托管内部gem。我读到了http://docs.rubygems.org/read/chapter/18.但是那个没有身份验证-如我所见。然后我读到了https://github.com/cwninja/geminabox.但是当我使用基本身份验证(他们在他们的Wiki中有)时,它会提示从我的服务器获取源。所以。如何制作带有身份验证的私有(private)Rubygem服务器?这是不可能的吗?谢谢。编辑:Geminabox问题。我尝试“捆绑”以安装新的gem..

  3. ruby-on-rails - 启动 Rails 服务器时 ImageMagick 的警告 - 2

    最近,当我启动我的Rails服务器时,我收到了一长串警告。虽然它不影响我的应用程序,但我想知道如何解决这些警告。我的估计是imagemagick以某种方式被调用了两次?当我在警告前后检查我的git日志时。我想知道如何解决这个问题。-bcrypt-ruby(3.1.2)-better_errors(1.0.1)+bcrypt(3.1.7)+bcrypt-ruby(3.1.5)-bcrypt(>=3.1.3)+better_errors(1.1.0)bcrypt和imagemagick有关系吗?/Users/rbchris/.rbenv/versions/2.0.0-p247/lib/ru

  4. ruby-on-rails - s3_direct_upload 在生产服务器中不工作 - 2

    在Rails4.0.2中,我使用s3_direct_upload和aws-sdkgems直接为s3存储桶上传文件。在开发环境中它工作正常,但在生产环境中它会抛出如下错误,ActionView::Template::Error(noimplicitconversionofnilintoString)在View中,create_cv_url,:id=>"s3_uploader",:key=>"cv_uploads/{unique_id}/${filename}",:key_starts_with=>"cv_uploads/",:callback_param=>"cv[direct_uplo

  5. Ruby——嵌套类和子类是一回事吗? - 2

    下面例子中的Nested和Child有什么区别?是否只是同一事物的不同语法?classParentclassNested...endendclassChild 最佳答案 不,它们是不同的。嵌套:Computer之外的“Processor”类只能作为Computer::Processor访问。嵌套为内部类(namespace)提供上下文。对于ruby​​解释器Computer和Computer::Processor只是两个独立的类。classComputerclassProcessor#Tocreateanobjectforthisc

  6. ruby - 用 Ruby 编写一个简单的网络服务器 - 2

    我想在Ruby中创建一个用于开发目的的极其简单的Web服务器(不,不想使用现成的解决方案)。代码如下:#!/usr/bin/rubyrequire'socket'server=TCPServer.new('127.0.0.1',8080)whileconnection=server.acceptheaders=[]length=0whileline=connection.getsheaders想法是从命令行运行这个脚本,提供另一个脚本,它将在其标准输入上获取请求,并在其标准输出上返回完整的响应。到目前为止一切顺利,但事实证明这真的很脆弱,因为它在第二个请求上中断并出现错误:/usr/b

  7. ruby-on-rails - 在 Rails 中调试生产服务器 - 2

    您如何在Rails中的实时服务器上进行有效调试,无论是在测试版/生产服务器上?我试过直接在服务器上修改文件,然后重启应用,但是修改好像没有生效,或者需要很长时间(缓存?)我也试过在本地做“脚本/服务器生产”,但是那很慢另一种选择是编码和部署,但效率很低。有人对他们如何有效地做到这一点有任何见解吗? 最佳答案 我会回答你的问题,即使我不同意这种热修补服务器代码的方式:)首先,你真的确定你已经重启了服务器吗?您可以通过跟踪日志文件来检查它。您更改的代码显示的View可能会被缓存。缓存页面位于tmp/cache文件夹下。您可以尝试手动删除

  8. ruby - Ruby 中的隐式返回值是怎么回事? - 2

    所以我开始关注ruby​​,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出

  9. ruby - 我的 Ruby IRC 机器人没有连接到 IRC 服务器。我究竟做错了什么? - 2

    require"socket"server="irc.rizon.net"port="6667"nick="RubyIRCBot"channel="#0x40"s=TCPSocket.open(server,port)s.print("USERTesting",0)s.print("NICK#{nick}",0)s.print("JOIN#{channel}",0)这个IRC机器人没有连接到IRC服务器,我做错了什么? 最佳答案 失败并显示此消息::irc.shakeababy.net461*USER:Notenoughparame

  10. ruby - Rails 开发服务器、PDFKit 和多线程 - 2

    我有一个使用PDFKit呈现网页的pdf版本的Rails应用程序。我使用Thin作为开发服务器。问题是当我处于开发模式时。当我使用“bundleexecrailss”启动我的服务器并尝试呈现任何PDF时,整个过程会陷入僵局,因为当您呈现PDF时,会向服务器请求一些额外的资源,如图像和css,看起来只有一个线程.如何配置Rails开发服务器以运行多个工作线程?非常感谢。 最佳答案 我找到的最简单的解决方案是unicorn.geminstallunicorn创建一个unicorn.conf:worker_processes3然后使用它:

随机推荐