摘要:本文主要带你们了解服务稳定性的重要性和相关策略。策略大概分两部分,第一方面从架构层面介绍保障服务稳定性的常见策略(限流,降级,隔离,超时,重试和集群)。第二个方面是从流程方面(code review, 压测,灰度和监控)讲解怎么去保证稳定性。php
https://www.infoq.cn/article/69TYjy_v9u4FxXNUk2gKredis
演讲嘉宾简介:算法
信海龙 (花名沧龙),十余年的互联网开发经验,2013 年加入阿里巴巴,深耕于电商、社区相关应用开发与架构。同时也是多个开源项目的开发者和维护者。表明开源做品,tclip,基于人脸识别的图片裁剪扩展。数据库
本次直播视频精彩回顾,戳这里!后端
直播回顾缓存
PPT 分享服务器
如下内容根据演讲嘉宾视频和 PPT 分享整理而成。网络
本次的分享主要围绕如下三个方面:架构
对不少企业来讲服务稳定性很是重要,首先稳定性问题会对企业带来直接的经济损失。举例来讲,亚马逊的“Prime Day”当天出现的一个故障,给亚马逊带来了高达 9900 万美圆的损失。这一个故障损失就多是其它小公司市值的几倍。因此服务稳定性对公司影响是特别大的。而对于我的来讲,服务不稳定性会影响员工的绩效,甚至影响我的前程。并发
从架构层面保障稳定性,常见的策略包括限流,降级,隔离,超时,重试和集群等。
限流目的
限流的目的主要有两点,第一点是防止系统高负荷运行,第二点是有效利用服务器资源。为何要作限流?假如不封锁请求,可能会致使服务器报警,若是平时服务器只能处理 100 个请求,忽然多出两个请求服务器或许勉强可以处理,但忽然多了 500 个请求的话,后面的 400 个请求只处在积压状态,等服务器处理到第 500 个请求的时候,用户等待时间就会过长,并且最后积压部分的请求可能根本就是无效的处理,由于用户早已流失。
限流算法
常见限流的算法包括漏桶算法和令牌桶算法。漏桶算法以下图,图中的例子有个小桶,桶下面有个孔,每流一滴水就能够认为是一个请求进去。滴水的速率是同样的,孔的高度也是固定的。漏桶算法能保证每一个请求的负载时长,即肯定每秒能处理的请求数量。
漏痛算法实现以下图,能够设定桶的高度是 5 个,每秒漏两个。执行效果中前面 5 次结果都是 true,以后中间一次结果是 false,这说明桶已经装满,以后又漏了两滴水,由于 false 的时候 sleep 了一秒,因此下面又有两个 true 出来。
令牌桶算法
以下图,令牌桶算法也是有一个桶,可是桶不漏,桶里面放了一些令牌,每来一个请求就在桶里拿一个令牌,若是没有令牌它就能够等待,令牌满了就再也不往里面加令牌。这样方法基本上也能够达到一个限流的目的。令牌桶算法和漏桶算法的一个显著区别是漏桶算法在后端取请求量时,基本上漏的速率是同样的,可是令牌桶算法中后端部分能够有突发请求,若是桶满了,能够将桶里全部令牌都拿走。
下图是令牌桶算法 lua 代码实现部分,固然读者还可使用 Nginx,Java 脚本或者 php 脚原本实现。
社区降级案例
通常状况下,系统上线以后总会遇到一些不稳定状况,好比 redis 挂掉,甚至后端数据库 My SQL 挂掉。当出现不稳定状况以后,系统如何保证继续提供这些服务。以社区案例为例,即使是 My SQL 挂掉,也要可以保证社区为用户提供基本的可读服务。其中一个策略是将一些热点数据,即用户常常浏览的信息或者最新的信息缓存起来,当后端服务不可用的时候,把这些数据展示给用户。大概流程以下图,数据存储部分后端会有一个脚本去分析 Nginx 里面的日志,而后去请求 Vanish,Vanish 再去请求后端,这样的话 Vanish 会有一个有效期,可以保证 Vanish 存进去的数据都是用户常常访问的一些数据。第二步,如何保证后端数据库挂掉的数据时候能迁过去?下图能够看到,Nginx 中使用 lua 脚本进行实现,它会检测后端服务返回的一些状态,使用计数器计算失败次数,若是频繁的达到必定程度的失败次数,就切换到从 Vanish 获取数据,最后推送给用户。这样能保证即使是后端的数据库挂掉,甚至即使全部的 php 进程都挂掉的时候,社区也能给用户提供一些基本的服务。
降级目的
降级的目的比较简单,第一个是保障服务器基本可用,第二个是保障服务的核心服务可用。降级是怎么一个思路呢?通常降级的每一个策略都是针对一个场景,预想特定场景下须要要解决什么问题;而后再梳理在这个场景下须要保留哪些核心基本服务;最后才选定技术方案,系统化的进行实现。简单讲就是先肯定须要达到什么目的,再去了解是什么样的状况,最后制定策略或者计划。好比,系统会调用第三方服务,而第三方服务有可能挂掉,这是一种典型的场景。再好比,系统自己调用推荐服务,可是推荐服务也会挂掉,这种场景下不可以由于没有推荐数据就不显示数据,仍是须要展现一些数据,这是一种基本的核心服务。每一年的双 11 或者一些大型活动中基本都会存在降级。降级不只仅是存在于资源故障场景下,资源不够用时也可能会须要降级,由于资源不够用须要关注重点。如大促活动中,须要先保证交易服务正常运行,其它消耗资源的服务(如对帐)能够后续再去处理。
超时案例
社区对外提供接口服务,对方的反馈是接口服务较慢。接口部分流程是查一段数据,而后将数据反映过去,其问题点在于系统中超时时间设置过长。好比调用 Memcache,可是 Memcache 已经挂掉,因为超时设置过长,数据须要等到超时时间结束之后再返回,致使接口一直在等待。那如何设置超时时间才合理?要注意超时时间并非固定的值,而是须要针对整个业务,根据特定场景设置超时时间值。
如何设置超时时间
大致的思路以下图。第一步,识别业务须要的服务响应时间。好比,须要 100 毫秒去响应数据,以后统计业务里面可能须要调多少服务。第二步,统计服务平常的响应时间。第三步,分清主次,即分出哪些是核心服务。由于核心服务一旦失败,整个链路便不可用,因此能够对核心服务的时间设置的宽松一些。若是一些服务调不通,但又不影响整个链路,能够对它的时间设置的相对严格。
设置完超时以后须要验证,借助模拟手段封端口(以下图),模拟故障,而后检查数据返回时间是否在指定的时间内。
隔离案例
下 2013 年左右,手机客户端开始逐渐升级起来,不少项目既有 PC 端也有客户端,因此同一个服务即要为 PC 端又要为客户端提供 API 接口。一旦遇到大型活动或者须要手机推送,服务会遇到不稳定状况,服务的不稳定会致使 PC 端也受影响,因此须要将服务进行物理隔离,从原先耦合到一块的服务器分到不一样的机器组。隔离目的很是简单,要限制住不稳定因素致使的风险,中止传播。
隔离形式
隔离的常见形式包括几种。第一是秒杀场景,秒杀场景一个高并发的场景,可能带来的问题也比较多,在高并发场景下秒杀的时候,须要和一些正常的业务区分开来,不建议一台机器既提供秒杀也提供进程服务。另外,秒杀的时候会产生热点数据,如售卖数据。数据库更新比较频繁,从数据库层面也能够进行隔离,将热点部分和正常服务部分从资源上隔离。第二个场景是慢 SQL 隔离,一个资源隔离。一条慢 SQL 会致使整个服务不稳定。每请求一次线程,慢 SQL 会一直耗着当前线程,因此资源占用很是大。第三个场景是机房隔离。通常大公司都会作多机房部署,其目的就是确保稳定性。确保稳定性时不要作跨机房调用,不然耦合度会比较高,假如 A 调 B,B 挂掉,A 服务也会受影响。通常确保稳定性都是作本机房的调用。并且本机房的调用性能也比较快。最后一个场景是进程隔离,由于进程比线程更加稳定。
对小公司而言,一台机器就提供一个服务,若是机器挂掉服务恢复就会成为一个问题。通常解决方法是作一个集群,从原来的一台机器提供服务变为能够用多台机器提供服务。集群的目的是为了解决单点的问题。集群的形式主要有主备,即同时只有一台机器提供整个服务,能够有一台或者多台提供备份,备份不只要包含代码层面,整个服务运行所依赖的资源都要有备份。另一个形式是主从。主是提供一个完整的服务,从是提供部分的服务。还有一种是多主,多主指的是每一台机器的决策是对等的,都会对外提供一些服务。随着集群形式的不一样,对代码编写的并发性上有必定要求。主备只须要考虑单机的并发控制,主从是考虑同时提供服务的部分。好比加锁,主备上只要加一个本地的技能锁就能够,主从或者多主则须要加分布式锁。
保证稳定性策略的流程方面上分为下图中四个点,code review, 压测,灰度和监控。
code review 目的是在项目上线前及时发现一些问题。经验比较丰富的人能够将经验进行分享。code review 基本通过三个阶段。第一个阶段是头脑风暴式,一群开发人员围着代码作 code review,虽然时间成本较高,效果也不太理想,可是这种方式也有好处,在前期能够将你们的意见进行整理,制定 code review 的规范。第二种 code review 形式是演讲式,专家事先把代码作一下 review,整理一些点,而后进行分享。演讲式能够按照轮岗制,相对头脑风暴式大大节约了时间。目前常见的 code review 形式是结对式,由一个或者两个专家结对,相互 review,时间上比较灵活,也不须要占据会议室资源。
压测目的
压测的目的,第一是保证系统稳定性。在高并发的时候,检测系统是否稳定,由于一些问题在流量比较低的时候发现不了,只有在高并发的时候才能发现这个问题。第二是检测性能的抗压能力,检查系统能承受多大的 QPS。
压测关注点
首先,压测机器和被压测服务在同一网段,尽可能避免由于网络缘由致使压测的结果不许确。第二点是关注服务器的负载,注意不要把服务器压到 100%,服务器快要崩的时候,获得的值意义不大。应该是服务器负载达到 60%~70% 的时候,看 QPS 是多少。另外,压测并发数据是逐步递增的过程,到一个点的时候,并发数据越多表明 QPS 越低。最后,根据测试环境的压测结果估算线上的承载能力。估算的公式是线上 QPS = 单机 QPS 机器数 0.7。后面会乘以一个系数(0.7)是由于线上 put 上去的时候总会存在一些损耗。
全链路压测
但有一些测试在测试环境下没法实现压测,因此如今发展成了全链路压测。全链路压测大概分红三个核心关注点。第一个是数据模型的构造。全链路压测是模拟线上真正的数据模型,好比说访问详情页的人数,下单的人数,人数比例,登录人数等等参数,尽可能按照真实数据模拟,构建仿真模型,这样才能真正的发现线上的一些问题。注意全链路压测不是在测试环境下实现,而是在线上压测。第二个是压测工具构建。能够是借助开源的压测工具,阿里自建了压测平台,根据数据模型提高流量。第三点是流量的隔离。对流量增长标识,保证不影响线上的数据,将全链路测试流量放到测试的存储中。好比生成一个订单 order 表,同时也会生成一个影子表 test_order。若是发现是来自于全链路压测的流量,就把这个数据写到影子表 test_order 里面,这样可以保证存储。不管是缓存仍是数据库存储都可以进行流量隔离。
灰度目的是小范围试错,尽可能发现问题。灰度的策略大概有如下几种,第一个策略是只让某一个地区的人先访问最新的特性,遇到问题的话用户及时反馈,问题也只会影响特定地区。另一个策略是基于用户属性,如一个推荐系统,请求过来的时候能区分新老用户,它对新老用户的推荐的策略多是不同的,从而来验证策略的准确性和有效性。第三种策略是基于数据,从一批用户中选取几个用户进行处理。好比,对供应链的供应商的数据作处理,可是通常状况下不敢保证代码上线以后 100% 没问题。这时先选择一个供应商处理,验证数据,确保没问题再全量处理全部的供应商。最后是基于平台,通常都发生在客户端场景下。客户端与服务端不一样,服务端通常是针对这个平台,先指挥这个平台先发布新版本,反馈不错再推到整个全面平台。对于客户端的灰度技术的实现以下图,给客户端集中一个 Cookie,请求到了以后在 Nginx 中去检查 Cookie,根据不一样的 Cookie 把情趣转到不一样的组。好比组 A 有新特性,组 B 是老版本,根据不一样的 Cookie 转到不一样组,保证只有一部分人能够看到新的特性。
监控注意点
监控的目的是能够自动化及时发现问题。监控须要注意几点问题,第一是全方面监控,系统和服务所有都要监控。第二是报警分级,监控报警的系数设置的要合理。最后一点是在真实环境下作数据收集。好比,A 和 B 服务器,只在 B 服务器作监控。若是 A 服务器 My SQL 数据库网络出问题后,由于在监控上 B 服务器是正常的,监控不会报警。因此要在应用服务器上作监控才会报警具体哪台机器哪一个服务出现故障等信息。
自研监控系统
下图是阿里自研的监控系统。首先肯定对哪些指标进行监控。将整个指标的数据绘制出来,查看指标数据波动。一旦遇到问题,能够很方便的进行对比。另外要肯定影响,将全部相关的指标聚合起来。好比供应商的团队操控系统常常会发生仓库操做卡顿,有不少因素都会致使卡顿,如 PC 端调用其它接口较慢,服务器 load 比较高等。仓库人员没法关注具体的细节,他们在影响界面查看指标影响值,一眼就能够知道是哪项指标不合格致使的卡顿。以后对形成的影响进行相应的处理,目前通常的行为有效报警或短信报警。
原文连接:
https://yq.aliyun.com/articles/699892?spm=a2c4e.11157919.spm-cont-list.33.146c27aelCf6gR