加速体育业务布局,CAA中国宣布并购体育公司凌势动力
06-18
在流量高峰下构建高服务质量的架构是一个挑战。本文是哔哩哔哩技术总监毛健先生在“腾讯云开发者社区沙龙线上”上分享的,基于Google SRE的系统方法论和实际业务响应流程,整理和阐述了一些系统化的可用性设计。
这将进一步帮助我们了解系统的整体情况以及上下游的联防。点击视频查看完整直播回放 1、负载均衡 负载均衡分为两个方向,一个是前端负载均衡,一个是数据中心内部的负载均衡。
在前端负载均衡方面,一般来说,用户流量访问级别主要是基于DNS,希望尽量减少用户请求的延迟。将用户流量优化分配在多个网络链路、多个数据中心、多个服务器上,通过动态CDN解决方案实现最小延迟。
以上图为例,用户流量首先会流入BFE的前端接入层。第一层BFE实际上充当路由器的角色。
它选择尽可能靠近接入节点的机房来加速用户请求。然后通过API网关转发到下游的服务层,可能是内部的一些微服务或者业务聚合层等,最终形成完整的流量模式。
基于此,前端服务器的负载均衡主要考虑几个逻辑:首先,尽量选择最近的节点;其次,根据带宽策略调度选择API进入机房;第三,根据可用服务能力平衡流量。就数据中心内部的负载均衡而言,理想情况下,如上图右侧所示,最繁忙和最不繁忙的节点之间的CPU消耗差异很小。
但如果负载均衡做得不好的话,情况可能会和上图左侧大不相同。这可能会导致资源调度和编排困难,无法合理分配容器资源。
因此,数据中心内部负载均衡的主要考虑因素是:均衡流量分配;可靠识别异常节点;横向扩展,添加同构节点以扩展容量;减少错误并提高可用性。之前我们发现通过同构节点扩容时,内网服务出现异常,CPU占用率较高。
通过排查,我们发现其背后的RPC点对点通信的健康检查成本过高,导致了一些问题。另一方面,如果底层服务只有单个集群,出现抖动时故障面会比较大,因此需要引入多个集群来解决问题。
通过实现从客户端到后端的连接子集,我们可以将后端均匀分配给客户端,处理节点变化,持续平衡连接,避免重大变化。多集群的情况下,需要考虑集群迁移的运维成本,并且集群之间的业务数据存在少量重叠。
回到繁忙和空闲时CPU占用过多的问题,我们会发现这与负载均衡算法有关。第一个问题是,对于每一个qps,其实每一次查询、查询、API请求,它们的成本是不同的。
节点之间的差异非常大。即使你做了均衡的流量分配,从负载的角度来看,其实还是不均匀的。
第二个问题是物理机环境存在差异。因为我们通常会逐年购买服务器,新购买的服务器通常具有更强的主频和CPU,因此服务器本质上很难做到高度同质化。
基于此,参考JSQ(最少轮转训练)负载均衡算法带来的问题,我们发现缺少的是服务器的全局视图,所以我们的目标需要综合考虑负载和可用性。我们参考《The power of two choices in randomized load balancing》的思想,使用choice-of-2算法对两个随机选择的节点进行评分,选择较好的节点:选择后端:CPU,客户端:健康状况、飞行中、延迟作为指标,并使用a使用简单的线性方程进行评分;对于新启动的节点使用恒定的惩罚值(penalty),并使用探针来最小化音量和预热;分数相对较低的节点将被阻止进入“永久黑名单”并且无法恢复。
利用统计衰减将节点指标逐渐恢复到初始状态(即默认值)。优化负载均衡算法后,我们取得了比较好的回报。
2. 限流以避免过载是负载平衡的一个重要目标。随着压力的增加,无论负载均衡策略多么有效,系统的某些部分总会出现过载。
我们优先考虑优雅降级、返回低质量结果并提供有损服务。最坏的情况下,需要适当的节流来保证服务本身的稳定性。
在限流方面,我们认为应该重点关注以下几点:一是qps的限制,带来请求成本不同、静态阈值配置困难的问题;其次,根据API的重要性,按照优先级丢弃;第三,给每个个人用户设定限制。当全局过载发生时,控制某些“异常”非常重要;第四,拒绝请求也是要花钱的;第五,为每个服务配置限流带来的运维成本。
关于限流策略,我们首先采用分布式限流。我们实现一个quota-server来为后端控制每个客户端,即后端需要请求quota-server来获取配额。
这样做的好处是减少向服务器请求的频率,获取后直接在本地消费。在算法层面,采用max-min公平算法来解决某个大消费者造成的饥饿问题。
在客户端,当用户超出资源配额时,后端任务会快速拒绝该请求,并返回“配额不足”错误。后端可能正忙于发送被拒绝的请求,从而导致过载和依赖资源。
错误较多,为了保护下游,我们选择直接在客户端进行流量,不发送到网络层。我们在 Google SRE 中学到了一个有趣的公式,max(0, (requests- K*accepts) / (requests + 1))。
通过这个公式,我们可以让客户端直接发送请求,一旦超过限制,就会按照概率进行流量拦截。在过载保护方面,其核心思想是在业务过载时丢弃一定量的流量,以保证系统接近过载时的峰值流量,以达到自我保护的目的。
常见做法包括根据CPU和内存使用情况丢弃流量;使用队列进行管理;可控延迟算法:CoDel等。简单来说,当我们的CPU达到80%的时候,这个时候就可以认为已经接近过载了。
如果此时的吞吐量达到了请求的瞬时值,我就可以丢掉这10个流了。在这种情况下,服务将可以进行自我保护。
基于这个想法,我们最终实现了一种过载保护算法。我们使用 CPU 的滑动平均值 (CPU > ) 作为启发式阈值。
一旦触发,即进入过载保护阶段。算法为:(MaxPass * AvgRT) < InFlight。
其中,MaxPass和AvgRT是触发前滑动时间窗口的统计值。限流效果生效后,CPU会在临界值()附近抖动。
如果不利用冷却时间,短暂的CPU下降可能会导致大量请求被释放,严重时CPU会被占满。冷却时间结束后,重新判断阈值(CPU > ),确定是否继续进入过载保护。
3. 重试流量的方向通常是从BFE到SLB,然后通过API网关到BFF、微服务,最后到数据库。这个过程要经历很多层。
在我们的日常工作中,当请求返回错误并且某些后端节点过载时,我们该怎么办?首先,我们需要限制重试次数以及基于重试分布的策略;其次,我们应该只在故障层重试。当重试仍然失败时,我们需要全局商定一个错误码,以避免级联重试;另外,我们需要使用随机的、指数增加的富集周期,这里可以参考Exponential Backoff and Jitter;最后,我们需要设置重试率指标来进行故障诊断。
在客户端,需要进行限速。由于用户总是会频繁尝试访问无法访问的服务,因此客户端需要限制请求的频率,可以通过接口级别的error_details挂载到各个API返回的响应中。
4、超时我们之前说过,大多数故障都是由于超时控制不合理造成的。首先首当其冲的是高并发下的高延迟服务,导致客户端堆积、线程阻塞。
此时上游流量不断涌入,最终导致故障。所以理解超时本质上其实是一种Fail Fast策略,就是让我们的请求尽可能的消耗。
这样积累的请求基本上都被丢弃或者消耗掉了。另一方面,当上游超时已经返回给用户时,下游可能还在执行,这会造成资源的浪费。
还有一个问题,我们在调优下游服务时,超时时间如何配置,默认值策略又该如何设置?在生产环境中,我们经常会遇到诸如手抖或配置错误等导致配置失败或故障的问题。所以我们最好在框架层面做一些防御性的编程,尽量让它保持在合理的范围内。
进程内超时控制的关键是在开始请求的每个阶段(网络请求)之前检查是否有足够的剩余时间来处理请求。另外,这个过程中可能会有一些逻辑计算。
我们通常认为这个时间比较小,所以一般不去控制。现在很多RPC框架都实现了跨进程超时控制。
我们为什么要这样做?跨进程的超时控制也可以参考进程内的超时控制思想,通过RPC传输源数据,带到下游服务,然后利用配额继续传输,最终使得上下游链路没有问题。长于一秒。
5、级联故障的处理基于我们上面提到的四个方面,我们在处理级联故障时需要考虑以下要点。首先,我们需要尽可能避免超载。
因为如果节点相继失效,服务最终会崩溃,集群也可能宕机,所以我们提到了自我保护。其次,我们使用一些手段来限制电流。
它允许某个客户端在大流量并发请求时控制服务,使服务不会轻易死掉。另外,当我们无法提供正常服务时,我们还可以提供有损服务,牺牲一些非核心服务来保证关键服务,实现优雅降级。
第三,重试策略上,微服务内部尽可能回退,尽量考虑重试放大流量倍数对下游的影响。此外,我们还必须考虑到,当移动用户无法使用某个功能时,他们通常会频繁刷新页面。
这将造成交通影响。我们还需要配合移动端来控制流量。
第四,超时控制强调两点,进程内超时和跨进程传递。最终它的超时链接是由顶层节点决定的。
只要做到了这一点,我想大概率是不太可能出现级联故障的。第五,变革管理。
我们通常会因为一些变更而发布,所以我们还是需要加强变更管理。变革过程中的破坏性行为应该受到惩罚。
即使不是合适的人,我们也要惩罚他。吸引注意力。
六是极压测试和故障演练。做压力测试的时候,可能会报错就停止。
我建议即使报错最好还是继续加压,看看你的服务表现如何?超载情况下能否提供服务?安装过载保护算法后,继续加压,主动排斥,再与保险丝结合,产生立体保护效果。频繁的故障演练可以制作出一本可供大家学习的质量控制手册。
经常练习会减少恐慌的发生。当生产环境出现问题时,可以快速解决。
第七,考虑扩大、重启、消除有害流量。上图所示的参考是对上述策略的经典补充,也是解决各种服务问题的玄学《腾讯云开发者社区》公众号回复“在线沙龙”即可获取PPT下载链接~ 6. Q&AQ:请问基于负载均衡的指标有哪些? A:我们在使用服务器的时候,主要使用的是CPU。
我认为CPU是最好的代表。从客户端的角度来说,我用的是health,指的是连接的成功率。
延迟也是一个非常重要的指标。另外,我们需要考虑每个客户端向不同后端发送多少请求。
Q:BFE到SLB是通过公网还是专线?答:这个其实有公网和专线。 Q:如果客户端每10秒几千个乒乓次的量级,实际上只有几百个qps?会造成相当高的CPU开销吗? A:如果你有几千个客户,但是你的各种上游服务加起来客户数量非常多,可能超过一万个。
所以会造成相当高的CPU开销,因为很多不同的应用程序来进行健康检查,这实际上是一个非常大的量。 Q:多集群的成本是如何考虑的?答:子簇。
上面说的多集群更多的是在同一个机房??布置多个集群。那么对于这个多集群来说,首先它必须有冗余的、一倍的资源。
这确实需要一定的成本,所以我们不会对所有服务都做这种冗余,只针对核心服务。所以本质上我们需要花一些钱,做一些冗余来尽可能的提高我们的可用性,因为一旦你的底层服务出现故障,它的故障面真的会蔓延得很广。
Q:超时投递的要求是否太严格?如果其中一个节点出现问题,就无法工作。A:这个策略是超时发送。
我们默认发货。在某些情况下,即使超时也会继续运行。
实际上可以通过我们的上下文覆盖此行为,因此它仍然取决于您的代码。逻辑处理。
Q:用户接入节点的质量和容量如何平衡?答:取决于调度策略。一般来说,你首先需要看看你的服务目的。
如果是注重用户体验或者功能性的话,我认为质量是优先考虑的。其次,如果你转发的机房没有超载,尽量转发到最近的节点。
在极端情况下,您的机房可能会超载。这种情况下就得通过接入节点转发到其他核心机房。
。讲师简介 毛健,bilibili技术总监,腾讯云最有价值专家(TVP) 毛健,bilibili技术总监,腾讯云最有价值专家(TVP)。
负责bilibili数据平台部门,拥有近十年服务器开发经验。擅长高性能高可用服务器开发,熟悉Go、Java、C等语言。
参与了哔哩哔哩从单体架构到微服务的完整转型,包括微服务治理、微服务可用性设计、微服务数据一致性设计、微服务中间件、微服务监控、微服务日志收集、微服务负载均衡、微服务RPC框架开发等。
版权声明:本文内容由互联网用户自发贡献,本站不拥有所有权,不承担相关法律责任。如果发现本站有涉嫌抄袭的内容,欢迎发送邮件 举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。
标签:
相关文章
06-18
06-06
06-18
06-08
06-18
最新文章
【玩转GPU】ControlNet初学者生存指南
【实战】获取小程序中用户的城市信息(附源码)
包雪雪简单介绍Vue.js:开学
Go进阶:使用Gin框架简单实现服务端渲染
线程池介绍及实际案例分享
JMeter 注释 18 - JMeter 常用配置组件介绍
基于Sentry的大数据权限解决方案
【云+社区年度征文集】GPE监控介绍及使用