查看原文
其他

你的API会自适应「弹性」限流吗?

侯树成 Tomcat那些事儿 2021-03-14


随着 Spring Cloud 等「开箱即用」组件的普及, 微服务变的越来越流行。而微服务中的稳定性则显得更加重要。因此,为了保证系统的稳定性,鲁棒性。


在应用开发中,我们一般会通过熔断、限流等方式来保障服务的稳定性。

本次我们重点来看看限制,限流中的「自适应」限流 - 根据服务器的性能等各个方面自动评估,达到最优的效果。


我们知道,随着请求流量的增加,服务器的资源被占用越来越多,所有的请求的 latency 会越来越大,最终请求超过系统的承受能力时,会出现请求超时、失败,直至最后服务挂掉。

而保证服务的可用性,减少系统服务的中断时间,是应用开发追求的目标。


本次我们主要来谈谈限流。



像上图所示,一般系统处理请求,如果超过当前的处理量,要么进入队列等待,要么被拒绝访问。这个了解线程池的设计原理的朋友应该都清楚。如果一个系统不设置任何限制,这个队列将会不断增长,所有请求都开始超时、失败直到系统崩溃。一个系统的超时、出错甚至会引发一整套系统的关联崩溃(雪崩)。


那关键是这个限制应该设置成多少呢?


这里核心的限制,也就是我们所谓的限流,是指给对外暴露的API增加流量限制,这样避免流量突增时应用被压垮。


像上图所示,系统在请求超过容量时出现超时、失败,资源占用处理不过来等各种现象,直至出问题。


那要限制请求,该从哪些方面入手呢?


如果你了解过限流相关的概念,会发现像「限流」或者叫「流控」这种API的防护,一般都是限制并发请求速度或者时间窗口内的请求速度。一般会通过以下几个方面进行限制:


漏桶算法


令牌桶算法


现在已经有不少开源工具可供使用,像 Guava 的RateLimiter,像 Sentinel等。基本也是采用上述两种思想实现。


但是这里有个问题:


如果要设置限制的线程数,或者说令牌桶这种算法,一次要提供多少令牌呢?


这些就需要依赖不少的经验或者说要经过不断的分析调整,从而达到一个理想的效果。


但是对于我们分布式的 API 的服务能力,其实是动态变化的。比如有些时候,会增加节点,甚至不同服务器的处理能力也不相同。这种「静态」的进行限流的方式,并不能很好的达到资源有效利用的效果。


既然看到了静态,我们一定会想到,有没有一种「动态」的方式来评估这个限流数该设置成多少合适呢?


去年, Netflix (对,没看错,就是那个 Hystrix,Zuul 等多个组件被集成到 Spring Cloud 中的 Netflix)开源了一个自适应、弹性限流的组件 -  

concurrency-limits


在实现该动态组件前,Netflix 在寻找一种自动识别的并发限制,想到达到的理想限流状态是


  • 不需要手动配置

  • 不需要中心协调

  • 无需了解任何硬件或者系统的拓朴知识

  • 将变化代理到系统拓朴


经过调研,他们发现了 TCP 拥塞算法(TCP congestion control)。这个算法尝试确定可同时传输的分组数(拥塞窗口大小),而不会导致超时或增加延迟。 算法跟踪各种指标去估算系统的并发限制并不断调整拥塞窗口大小。


从上面的图里我们看到,系统的初始状态,我们并不清楚具体的并发,如蓝色所示。 所以前期对于请求数的限制,以低并发开始,同时通过增加拥塞窗口,只要 latency 不增加,就可以调更高,来试探更高的并发。 当latency 确实增加时,假设已达到限制并退回到较小的拥塞窗口大小。 持续试探极限,这个过程就产生了上图的锯齿形状。这样就保证了系统拥有较低的 latency,整个系统也能正常运转。


Netflix 的自动调整的算法,核心思想源自上面说的 TCP 拥塞控制算法(TCP congestion control algorithm)。算法查看最小的延迟(代表没有排队的最佳情况)和时间采样延迟之间的比率,用于识别队列已形成并导致延迟上升的关键因素。比率给出了延迟变化的梯度或幅度:


gradient =(RTTnoload / RTTactual)。


值为1表示没有排队,并且可以增加限制。小于1的值表示形成了过多的队列,并且应该减少限制。对于每个新样本,使用此比率调整限制并使用简单公式添加允许的队列大小,


newLimit = currentLimit×gradient + queueSize


在几次迭代之后,算法收敛于一个限制,该限制使延迟保持低,同时允许一些排队来计算突发。


Netflix 在官方技术博文中很开心的说,他们终于不再需要「保姆式」的人工干预,并提高了微服务体系的稳定性和可用性。


As we roll out adaptive concurrency limits we’re eliminating the need to babysit and manually tune how our services shed load. Even more, it does it while simultaneously improving the overall reliability and availability of our whole microservice-based ecosystem.



所以,我们发现,一方面,借助这种更「聪明」的工具,我们的应用,也可以更加健壮,处理流量也更「得心应手」。另一方面,看似「古老」的技术内容,依然在给现代提供养分,让我们可以站的更高。


参考内容:

https://medium.com/@NetflixTechBlog/performance-under-load-3e6fa9a60581

文章中的图来源于上述文章


相关阅读

大白话描述并发编程重要概念

Java并发编程相关概念及注意事项

Tomcat 性能调优之 JVM 调优




PS:之前月底送书的名单,由于前一阵子每天加班到晚上十一二点,所以拖了很久,文章也没写,名单也没看,大家多见谅。今天公布名单:


George·D、341、郑星星 、丽萍、skolly、~*\.()?${}、姚小焕、嘴、思想在摇曳、SHY


恭喜以上获奖的读者,请加微信「richardhou000」,发快递信息以及所选书籍。没有中奖的读者多留言点赞混脸熟,多攒人品,后面会帮大家争取更多的福利。


更多常见问题,请关注公众号,在菜单「常见问题」中查看。


源码|实战|成长|职场

这里是「Tomcat那些事儿

请留下你的足迹

我们一起「终身成长」


识别二维码,关注我



                                                                  如有帮助,就给我一个“好看”吧

    您可能也对以下帖子感兴趣

    文章有问题?点此查看未经处理的缓存