博客|Netflix 技术博客:区分优先级的负载分流,保持服务的稳定可靠( 二 )


大多数情况下,请求工作流在不考虑请求优先级的情况下,也是可以正常运行的。不过,就像任何服务一样,有时我们也会遇到后端之一出问题或者Zuul出问题的的情况。一旦发生这种情况时,优先级更高的请求会被优先处理。优先级较高的请求会获得服务,而优先级较低的请求则不会。其实现类似于有着动态优先级阈值的优先级队列。这可以让Zuul丢弃优先级低于当前阈值的请求。
找到最好的流量控制点Zuul可以在请求生命周期的两个时刻应用减载:将请求路由到特定的后端服务(服务限制)时或在初始请求处理时,这会影响所有后端服务(全局限制)。
在请求的整个生命周期里,Zuul有两个时间点可以进行负载分流:一是当它将请求路由到特定的后端服务时(服务限流),二是在开始处理请求时,这会影响到所有的后端服务(全局限流)。
服务限流
Zuul可以通过监视错误率和对该服务的并发请求来感知后端服务何时出现问题。这两个指标是故障和延迟的近似指标。当超过这两个指标之一的阈值百分比时,我们将通过限制流量来减少服务负载。
通过监控错误率和对自己的并发请求量,Zuul可以觉察到服务什么时候出现了问题。这两个指标,是反映故障和延迟的大致指标,当其中一个指标超过阈值的百分之一时,我们会通过限制流量,来降低服务负载。
全局限流
另一种情况是Zuul本身出问题了。跟上面的情况相反,全局限流会影响Zuul后面所有的后端服务,而不是单个后端服务。这种全局限流的影响可能会给会员造成更大的问题。用来触发全局限流的关键指标,包括CPU利用率、并发请求数有一集连接数量,当任何一个指标超过阈值时,Zuul都会主动限制流量,从而在系统恢复的同时保持自身的正常运行。这个功能非常关键:如果Zuul出现故障,流量就不能通过我们的后端服务,从而导致服务全面中断。
引入基于优先级的逐步负载分流设置好优先级部分后,我们便可以将其与减载机制结合起来,从而大大提高流传输的可靠性。当我们处于恶劣情况下(即超过上述任何阈值)时,我们会从最低优先级开始逐渐减少流量。三次函数用于管理节流级别。如果情况真的变得非常糟糕,那么水平将触及曲线的尖角,从而限制一切。
在确定了优先级之后,我们就可以将其跟我们的负载分流机制结合起来,从而极大提高流媒体播放的可靠性。当我们遇到糟糕情况时(也就是上述任何指标超过阈值)时,我们会从最低优先级开始,逐步丢弃流量。我们用一个三次函数来管理限流级别,如果情况变得非常非常糟糕,限流的级别就会触及曲线的尖角,限制一切流量。
博客|Netflix 技术博客:区分优先级的负载分流,保持服务的稳定可靠
文章插图
上图是如何应用三次函数的示例。随着过载百分比的增加(即节流阈值和最大容量之间的范围),优先级阈值会非常缓慢地跟踪它:在35%时,它仍处于90年代中期。如果系统继续降级,我们会以超过80%的优先级达到50,然后达到95%的优先级10,依此类推。
上图是三次函数应用的一个示例。过载百分比不断增加(即限流阈值与最大容量之比),但优先级阈值变化依然不大:过载百分比为35%时,优先级阈值仍然在90左右。如果系统还在不断降级,在过载百分比超过80%的情况下,优先级阈值仍有50,然后在过载百分比达95%的情况下优先级阈值达到10。
考虑到相对少量的请求会影响流媒体播放的可用性,限制低优先级的流量可能会影响到某些产品功能,但不会影响会员按下“播放”并观看自己喜欢的节目。通过引入基于优先级的逐步负载分流,Zuul可以卸载掉足够的流量来稳定服务,又不会引起会员的注意。
应对重试风暴
当Zuul决定放弃流量时,它会向设备发送信号,让他们知道我们需要他们退后。它通过指示可以执行多少次重试以及可以在哪种时间范围内执行来实现此目的。例如:
当Zuul决定放弃流量时,它会向设备发送信号,让对方知道我们需要它们卸载流量。Zuul会告诉设备最大的重试次数,以及可以在什么样的时间窗口下执行这些重试命令,这样就解决了重试风暴的问题。比方说:
{“maxRetries”:,“retryAfterSeconds”:}
使用这种反压机制,我们可以比过去更快地停止重试风暴。我们会根据请求的优先级自动调整这两个拨盘。高优先级的请求将比低优先级的请求更积极地重试,这也提高了流式传输的可用性。