当前位置: 首页 > 后端技术 > PHP

阿里云栖开发者沙龙PHP技术专场——浅谈服务稳定性保障

时间:2023-03-29 18:24:12 PHP

摘要:本文主要介绍服务稳定性的重要性及相关攻略。该策略大致分为两部分。第一个方面介绍了从架构层面(限流、降级、隔离、超时、重试、集群)保障服务稳定性的常用策略。第二个方面是从流程(codereview、压测、灰度和监控)的角度讲解如何保证稳定性。主讲人简介:辛海龙(昵称苍龙),拥有十余年互联网开发经验。2013年加入阿里巴巴,深度参与电子商务及社区相关应用的开发与架构。他还是多个开源项目的开发者和维护者。代表开源作品,tclip,基于人脸识别的图像裁剪扩展。要查看此直播视频的精彩回顾,请单击此处!直播回顾:https://yq.aliyun.com/live/965PPT分享:https://yq.aliyun.com/download/3530以下内容根据嘉宾视频和PPT分享整理而成。本次分享主要围绕以下三个方面:稳定性的重要性、保障策略框架、保障策略流程、稳定性的重要性。服务稳定性对很多企业来说非常重要。经济损失。例如,亚马逊“PrimeDay”日的一次故障让亚马逊损失了9900万美元。这个失败损失可能是其他小公司市值的好几倍。因此,服务稳定性对公司的影响特别大。对于个人而言,服务的不稳定会影响员工的绩效,甚至会影响他们的个人前景。保障策略架构篇从架构层面保障稳定性。常见的策略有限流、降级、隔离、超时、重试、集群。1.限流的目的限流的目的主要有两个。一是防止系统高负载运行,二是有效利用服务器资源。为什么要限流?如果请求没有被阻塞,可能会导致服务器报警。如果服务器平时只能处理100个请求,服务器可能突然多了两个请求勉强可以处理,但是如果突然多了500个请求,后面的400个请求就只处于积压状态,当服务器处理第500个请求,用户会等待太久,最后一部分积压的请求可能根本处理不完,因为用户已经丢失了。限流算法常见的限流算法有漏桶算法和令牌桶算法。漏桶算法如下图所示。在图中的例子中,有一个小水桶,水桶下面有一个洞。每一滴水都可以视为进入的请求。滴水的速度是一样的,孔的高度也是固定的。漏桶算法可以保证每个请求的加载时长,即确定每秒可以处理的请求数。漏痛算法实现如下图所示。可以设置桶的高度为5,每秒有两次漏水。执行效果中,前5次的结果都是true,中间的结果是false,也就是说桶满了,然后漏了两滴水,因为为false的时候,它睡觉了一秒钟,所以下面还有两个真实的。令牌桶算法如下图所示。令牌桶算法也是有桶的,但是桶是不漏的。一些令牌放在桶中。每有一个请求过来,桶里就取一个token。如果没有令牌,它可以等待,当令牌已满时,不再向其添加令牌。这种方法基本可以达到限流的目的。令牌桶算法和漏桶算法的一个显着区别是,当漏桶算法从后端取请求时,泄漏率基本相同,但令牌桶算法的后端部分可能会出现突发请求。当它装满时,可以将桶中的令牌全部取走。下图是令牌桶算法的lua代码实现部分。当然读者也可以使用Nginx、Java脚本或者php脚本来实现。二、降级社区降级案例一般情况下,系统上线后,总会出现一些不稳定的情况,比如redis挂了,甚至是后台数据库MySQL挂了。当出现不稳定的情况时,系统如何保证继续提供这些服务。以社区案例为例,即使MySQL挂了,也必须能够保证社区为用户提供基本的可读服务。其中一种策略是缓存一些热点数据,即用户经常浏览的信息或最新的信息,在后端服务不可用时将这些数据呈现给用户。大致流程如下图所示。数据存储部分后台会有脚本分析Nginx中的日志,然后请求Vanish,Vanish会请求后台。这样Vanish就会有一个有效期,可以保证Vanish里面存储的数据是用户经常访问的一些数据。第二步,如何保证后端数据库挂掉的数据能够搬过来?如下图可以看出,Nginx是使用lua脚本实现的。它会检测后端服务返回的一些状态,并使用一个计数器来统计失败的次数。如果失败次数频繁达到一定程度,则切换到Vanish获取数据,最后推送给用户。这样可以保证即使后台数据库挂掉,甚至所有php进程挂掉,社区也能为用户提供一些基础服务。降级的目的比较简单。一是保证服务器基本可用,二是保证服务的核心服务可用。降级的思路是什么?一般来说,每一个降级策略都是针对一个场景,预测在特定的场景下需要解决什么问题;然后梳理出这个场景需要保留哪些核心基础服务;最终选择技术方案并系统实施。简单来说,就是先确定需要达到的目标,然后了解是什么样的情况,最后制定策略或计划。比如系统会调用第三方服务,第三方服务可能会挂掉。这是一个典型的场景。再比如,系统自己调用了推荐服务,但是推荐服务也会挂掉。该场景中,由于没有推荐数据,无法显示数据,但需要显示一些数据。这是一项基本的核心服务。基本上每年双11或者一些大型活动都会降级。降级不仅存在于资源失效的场景,在资源不足的时候也可能需要降级,因为不足的资源需要重点关注。例如,在促销活动中,需要先保证交易服务的正常运行,其他耗费资源的服务(如对账)可以稍后处理。3.timeout超时案例社区对外提供接口服务,对方反馈接口服务慢。接口过程的部分是检查一条数据,然后反映数据。问题是系统中的超时时间设置的太长了。比如调用了Memcache,但是Memcache已经挂起。由于超时设置过长,数据需要等到超时后才返回,导致接口等待。那么如何设置超时时间才合理呢?需要注意的是,超时时间不是一个固定值,需要根据整个业务的具体场景来设置。超时时间如何设置的大致思路如下图所示。第一步是确定业务所需的服务响应时间。比如响应数据需要100毫秒,然后统计业务中可能需要调整多少个服务。第二步统计服务每天的响应时间。第三步,区分主次,即哪些是核心服务。因为一旦核心服务出现故障,整个链路都会不可用,所以核心服务的时间可以设置的宽松一些。如果有些业务不能在不影响整个链路的情况下进行调整,可以给它设置一个比较严格的时间。设置超时后,需要验证,使用模拟手段封口(如下图),模拟故障,然后检查数据返回时间是否在规定时间内。4、隔离案例2013年前后,移动客户端开始逐步升级。很多项目既有PC也有客户端,所以同一个服务必须同时为PC和客户端提供API接口。一旦遇到大型活动或者需要手机推送,服务就会遇到不稳定的情况。服务的不稳定也会对PC端造成影响,所以需要对服务进行物理隔离,从原本耦合的服务器分到不同的机器上。团体。隔离的目的很简单,限制不稳定因素带来的风险,阻止传播。隔离形式常见的隔离形式包括几种。首先是秒杀场景。秒杀场景属于高并发场景,可能会出现很多问题。在高并发场景下进行秒杀时,需要和一些正常的业务区分开来。不建议一台机器既提供秒杀进程服务又提供。此外,秒杀过程中还会产生销售数据等热点数据。数据库更新频繁,也可以从数据库层面进行隔离,将热点部分和正常业务部分从资源上隔离开来。第二种场景是慢SQL隔离,一种资源隔离。一条慢SQL会导致整个服务不稳定。每请求一个线程,慢SQL总会消耗当前线程,所以资源占用非常大。第三种场景是机房隔离。一般大公司都会部署多个机房,目的是保证稳定性。在保证稳定性的情况下,不要跨机房调用,否则耦合度会比较高。如果A转给B,B挂了,A的业务也会受到影响。一般通过机房呼叫来保证稳定性。而且机房的调用性能比较快。最后一种情况是进程隔离,因为进程比线程更稳定。5、集群对于小公司来说,一台机器提供一种服务。如果机器挂了,服务恢复就会成为问题。一般的解决方案是搭建一个集群,从原来的一台机器提供服务,变成多台机器提供服务。集群的目的是解决单点问题。集群的主要形式有主备两种,即同时只有一台机器提供整个服务,一台或多台机器可以提供备份。备份不仅要包括代码层面,还要包括整个服务所依赖的资源。另一种形式是主从。master是提供完整的服务,slave是提供部分服务。另一种是多主。多主就是每台机器的决策都是平等的,都会对外提供一些服务。不同的集群形式,对代码编写的并发度有一定的要求。主从只需要考虑单机的并发控制,主从是考虑同时提供服务的部分。比如加锁,只需要在master和slave上加本地技能锁,在master-slave或者multi-master上需要加分布式锁。保障政策流程保障稳定政策流程分为下图四点,代码审查、压力测试、灰度和监控。1、代码审查代码审查的目的是在项目上线前及时发现一些问题。有更多经验的人可以分享他们的经验。代码审查基本上经历三个阶段。第一阶段是头脑风暴。一组开发人员围绕代码进行代码审查。虽然时间成本高,效果不理想,但这种方法也是有好处的。前期可以整理一下大家的意见,制定代码。评审规范。代码审查的第二种形式是演讲风格。高手提前审阅代码,整理出一些要点,再分享。可以按照轮流制轮流上课,比起脑力激荡节省了很多时间。目前,常见的代码审查形式是结对,由一到两名专家结对,相互审查。时间更灵活,不需要占用会议室资源。2.压力测试的目的压力测试的目的首先是保证系统的稳定性。并发高的时候检查系统是否稳定,因为有些问题在流量比较低的时候是发现不了的,只有并发高的时候才能发现这个问题。其次是检测性能的耐压性,检测系统能承受多少QPS。注重压测首先,压测机和被测服务在同一网段,尽量避免因网络原因导致压测结果不准确。第二点是要注意服务器的负载。小心不要将服务器按到100%。当服务器即将崩溃时,获取的值意义不大。应该是服务器负载达到60%~70%的时候,看QPS。另外,压测并发数据是一个逐渐增加的过程。当达到一个点时,更多的并发数据意味着更低的QPS。最后根据测试环境的压力测试结果预估在线承载能力。估算公式为在线QPS=单机QPS机器数0.7。后面还要乘一个系数(0.7),因为上线的时候总会有一些损失。全链路压测但是有些测试无法在测试环境中实现压测,所以现在发展为全链路压测。全链路压测大致分为三个核心关注点。首先是数据模型的构建。全链路压测是模拟线上真实的数据模型,比如详情页访问人数、下单人数、人数占比、登录人数等,尝试根据真实数据进行模拟,建立模拟模型,从而真正在线上发现一些问题。注意,全链路压测不是在测试环境下实现的,而是线上压测。二是构建压力测试工具。可能是借助开源压测工具,阿里搭建了自己的压测平台,基于数据模型来提升流量。第三点是交通的隔离。为流量添加标签,保证线上数据不受影响,将全链路测试流量放入测试存储。比如生成一张order表,同时生成一张影子表test_order。如果发现流量来自全链路压测,将此数据写入影子表test_order,可以保证存储。缓存和数据库存储都能够进行流量隔离。3.灰度灰度的目的是在小范围内尝试和犯错,尽可能多地尝试发现问题。灰度有以下策略。第一种策略是只允许特定地区的人首先访问最新功能。如有问题,用户会及时反馈,该问题只会影响特定区域。另一种策略是基于用户属性。例如,推荐系统可以在请求到来时区分新老用户。可以为新老用户推荐不同的策略,以验证策略的准确性和有效性。第三种策略是根据数据从一批用户中选出几个用户进行处理。比如供应链上的供应商的数据是经过处理的,但是一般情况下,代码上线后是无法保证100%ok的。这时先选择一个供应商进行处理,核实数据,确保没有问题后,再对所有供应商进行全面处理。最后是基于平台,一般发生在客户端场景。客户端不同于服务器。服务器一般都是针对这个平台的。它首先指挥平台发布新版本,如果反馈好,就会推送到整个综合平台。客户端灰度技术的实现如下图所示。为客户端收集一个cookie,请求到达后在Nginx中查看cookie,根据不同的cookie将兴趣转移到不同的组。比如A组有新功能,B组是老版本。根据不同的cookies,转移到不同的群组,确保只有部分人可以看到新功能。4、监控和监控注意点监控的目的是自动及时发现问题。监测需要注意几个问题。一是全方位监控,所有系统和服务都要监控。二是告警分类,监控告警的系数设置要合理。最后一点是在真实环境下做数据采集。比如A、B服务器只在B服务器上被监控。如果服务器A的MySQL数据库网络有问题,因为服务器B在监控上是正常的,监控不会报警。因此,需要在应用服务器上进行监控,报告是哪台机器或服务出现故障等信息。自研监控系统下图是阿里自研的监控系统。首先确定要监控哪些指标。绘制整个指标的数据,查看指标??数据的波动情况。一旦遇到问题,你可以很容易地对它们进行比较。还要确定影响,汇总所有相关指标。例如,供应商的团队控制系统经常在仓库操作中出现冻结。导致卡顿的因素有很多,比如PC端调用其他接口慢,服务器负载高等。仓库人员无法关注具体细节。他们在影响界面查看指标的影响值,一眼就能知道是哪个指标不合格导致冻结。之后,将对造成的影响进行相应的处理。目前,一般行为有效的是报警或发短信报警。本文作者:PHP小能手阅读原文本文为云栖社区原创内容,未经允许不得转载。