浅谈高可用度量及治理
高可用的度量
高可用的度量标准
一般来说,高可用的度量,采用《服务等级协议》(简称:SLA)。具体为:
- Service:服务,指提供给客户(内部客户、外部客户)的所有功能。提供功能的组织被称为服务提供者,通常是人、软件、软件的运行需要计算资源、以及软件系统的依赖。
- SLI:服务等级对象,指的是对象,测量指标。通常有:性能相关的响应时间(latency)、吞吐量(throughput)、请求量(qps)、实效性(freshness),可用性相关的运行时间(uptime)、故障时间/频率、可靠性,质量相关的准确性(accuracy)、正确性(correctness)、完整性(completeness)、覆盖率(coverage)、相关性(relevance),内部相关指标如队列长度(queue length)、内存占用(RAM usage),以及人相关的响应时间(time to response)、修复时间(time to fix)、修复率(fraction fixed)。
- SLO:服务等级目标,批的是目标,对提供服务的期望状态。SLO通过SLI来描述,通常为:99%时间访问延迟<500ms。
- SLA:服务等级协议,指的是协议,指SLO、以及后果。例如,将服务可用性从99.9%提高到99.99%所需要的资源、及带来的收益,是决定该服务是否应该提供4个9的重要依据。
高可用度量的若干问题
关于高可用中的几个9的计算
高可用指标来计算时间如下:
可用级别 | 年度停机时间 | 季度度停机时间 | 描述 |
---|---|---|---|
99% | 3.65天 | 21.9小时 | 基本可用性。其状态为:有经过认真测试过的系统,遇到故障能及时响应。 |
99.9% | 8小时45分钟 | 2.19小时 | 较高可用性。相对上一级别,在故障管理上,遇到问题能在2小时内响应。 |
99.95% | 4小时23分钟 | 64分钟 | 较高可用性。相对上一级别,在故障管理上,遇到问题能在2小时内响应。 |
99.99% | 52.5分钟 | 13分钟 | 具有故障自动恢复能力的可用性 。相对上一级别,需要有较强的自动恢复能力,监控到故障发生后,能自动处理故障。 |
高可用的投入有,越往后面的,投入就越高,当然也是有一些技巧的,如:充分利用缓存、SDK等。笔者所有的公司,核心业务的指标为:99.95%的时间,延迟<1s;关键链路的指标为:99.98%的时间,延迟<1s。
关于SLO设置的实践
- 需要指定好计算的时间窗口,如年度、季度、月度。一般来说,经严格测试过的系统,出现故障是个概率问题。假定故障处理时间是1.5小时,年度出现概率是3次,以99.95%的可用级别来说。基本上可以达到99.95%的年度可用级别,但只能达到99.9%的季度可用级别。
- 设置SLO时,建议:
- 首先要测试系统的当前状态,设立预期目标;
- 通过不断迭代,改进SLO;
- 设置内部SLO、以及外部SLO,保持一定安全缓冲;
- 常用的几种服务的SLO,简单计算方法:
- Web服务:
- HTTP请求错误率 = 统计周期内∑((每5分钟的失败请求数+每五分钟的超过1秒响应请求数)/每5分钟有效总请求数)/统计周期内5分钟总个数*100%
- 线上故障占比 = 统计周期内线上故障时长/统计周期总时长*100%
- 服务可用性 = 100% - MAX(HTTP请求错误率,线上故障占比)
- Web网关:
- 总服务可用性 =((服务周期总分钟数-服务不可用分钟数)/服务周期总分钟数)x100%
- 注:在在指定的TPS响应内,如:10W TPS ;
- 中间件,如MySql、Mongo、Redis
- 线上故障时长占比:不大于0.05%
- 99%时间内实例自动扩容时间在5分钟以内
- Web服务:
- SLO的建设,是管理+工具的结合:
- 管理上,需要有明确的故障响应机制、以及故障处理预案,以确保在指定的时间内完成故障处理,以及故障的排查,方便PDCA;
- 工具上,需要建立基本的监控、测量工具,以实时观测SLI的变化、以及必要的改进;
关于故障的透传性
在做高可用时,最麻烦的一个问题在于:服务的依赖性,会导致服务的可用性急剧降低。如:
- 服务 A,依赖服务B、以及MySql等中间件;
- 此时,如果 MySql的可用性及 99.95%,那么理论上服务A想要达到99.99%的可用性基本不可能了。
- 进一步,服务B也依赖MySql,那个服务A的可用性,为:99%=99.9%(服务A的MySql)* 99.95%(服务B的MySql);
当然,在实际工作中,可以通过缓存、熔断、降级等方案,在一定承度上解决上述的问题,但也比较有限。因此,在服务的调用链条中保证每个依赖的可用性。
高可用的治理
谈到高可用的治理,其主要目标为:
- 降低故障频次:通过合理的服务设计,提升服务自身的可用性,减少/弱化/优化服务的依赖,以及规范/控制服务的变更流程。
- 缩短故障时长:通过种监控工具、以及规范化的故障处理规范,实现快速的故障发现、定位,实现故障的快速处理/解决;
- 减小故障影响范围:在运维期,通过隔离、降级、限流、熔断等手段、以及编写各种故障预案,预防故障的发生,以及在故障发生期间实现控制故障的影响范围;
从高可用的目标描述中,比较自然的可以得出,高可用的实践工作包含: 管理工作、以及工具建设部分。实质上,两者都要并重进,才能将系统的可用性保持在较高的水平。正是依赖这两项工作的建设,核心业务的指标为:99.95%的时间,延迟<1s;关键链路的指标为:99.98%的时间,延迟<1s。
高可用管理工作
高可用的管理,主要体现在故障发生时,缩短故障时长、减少故障影响上。对于故障的处理,需要建立“线上故障快速上报、以及处理机制”,其要点:
OnCall
对于 OnCall的建设,其要点为:
- 建立7*24小时的值班制度,第一时间接收来自系统、以及来自于客户的故障反馈;
- 责任到人,除直接面向Oncall的值班人员外,还需要有能第一时间联系到相关的组件、产品负责人员列表;
- 信息公开,通过及时聊天工具,将相关的责任人员、BUG处理人员,拉到同一群里,及时反馈故障信息、以及故障处理进展;
- 适当故障升级,当故障无人处理(找不到BUG处理人员)、规定时间未修复(例如6小时内),可将故障升级到分管经理、总监;
- 故障验收,对于已处理完成的故障,OnCall值班及时确认告警/故障已经恢复,并在确认30分钟内未发生同类问题时,确认故障已经解决;
- 故障的奖惩,按故障和级别对相应的团队给予相应绩效减分;对于故障及时处理,给予一定的故障免罚/减罚处理,反之加重;
- 故障的等级,可分为:致命、严重、一般、轻微、建议,一般严重以上的级别才触发线上OnCall处理。
OnCall制度的建立,需要专业的团队负责。笔者所有公司早期OnCall团队的维护仅是归属于平台团队进行兼职维护,效果一直不理想,主要是动力不足、团队间协作问题等,后继改为VP直接带队后才有所改善。
应急预案
在OnCall值班人员接收到线上故障后,第一反应是:初步分析故障的原因,尝试通过“应急预案”恢复服务。
在高可用的预案机制中,关于预案描述,一般包含:
- 服务描述,如服务架构、服务依赖(如第三方服务、MySql、MQ等),以及服务的维护人员;
- 服务应急资源,如MySql扩容/故障备机等;
- 常见故障的处理,这边需要说明,故障排查工具(如中间件监控、链路工具、日志工具)、故障原因说明、以及故障应对方案;
典型的应急预案机制:
- 中间件(MySql、Redis、RabbitMQ等)
- 针对Master节点的故障,一般处理为:主从切换;
- 针对高并发响应,一般处理为:扩容/增加节点、以及将服务进行流量限制;
- Web网关(Nginx、KONG)
- 无状态服务,一般直接重启;
- Web服务
- 针对高并发响应,相对复杂,一般处理为:确认调用的API,上流量限流;然后排查依赖的第三方服务(通过调用链)、依赖中间件、以及自身的负载,确认扩容方案;
根因分析
故障的应急处理,是为了后面不再发生类似的问题。因此有必要事后,针对故障进行根因分析,在管理上形成PDCA。
对于根因分析,其要点为:
- 故障编号,一般对应BUG系统的bug id;
- 故障等级,一般为分致命、严重;
- 故障处理人,实际处理故障的执行人员;
- 故障责任人,故障发生组件/模块/功能的开发负责人;
- 影响范围,该内容比较难,除了描述影响的功能外,还要评估对产品产生的影响,如影响那些的产品、影响多少用户、以及给公司带来的损失(可能是小功能,但是用户都是重要岗位负责人,损失就很大);
- 故障时间,包含故障的发现时间、定位时间、恢复时间、解决时间(恢复可能是临时的,解决就把问题改正)、解决时长、发生环境(用户所在区域、用户的端等);
- 故障描述,故障时的表现,如页面异常、提交中断等;
- 故障定位,故障处理人收到故障后的排查、分析过程,描述要详细,以便事后回顾;
- 根据分析,针对该故障的分析,一般通过5W1H的分析方法,对故障进行层层分析,并根据原因给出改进说明;
根因分析,执行的主要问题在于需要组织定期复盘:故障分类、故障改进执行情况等。
变更管理
在高可用的管理中,特别讲到变更管理,主要原因在于,变更是微服务(分布式系统)中最容易发生问题的一个环节。关于变更,一般指:
- 组件/服务的发布/升级,这个过程中,往往会伴随着数据库的升级、配置变更(运行环境、系统配置等)、以及代码程序的升级等;
关于变更管理,主要由以下内容构成:
- 信息公开,通过资产管理进行产品、组件、及到服务的运营、部署公告,以方便各方获取相应的信息;
- 变更控制,对组件的部署时间进行控制,例如在用户低频访问期间做进行部署,以及避开产品运营活动;
- 建设预生产、以及蓝绿部署机制,通过该机制将业务上线前进行集成、测试,可以有效的避免线上集成问题;
- 对数据库升级、配置变更,需要有回滚能力,该工具的建设相对困难,特别是DB的回滚,涉及大量的数据记录,操作时间长,一般通过预生产做充分的演练;
- 需要有容量规划,涉及运行的环境、以及基础服务的支撑,包含:
- 业务规模,如TPS、用户数、增长量等;
- 计算资源,一般指Tomcat等Web实例的个数,以及每个实例的CPU、内存等;
- 存储容量,一般是DB等数据量, 以及DB的集群规模;
在一个高速的交付系统中,这种变更更加的频繁。笔者所在公司所开发的云服务,拥有5K+个微服务,每周发布1K+次,如果有0.1%的部署会产生问题,那么每周至少发生一次故障。当然,为了避免问题的扩散,通常都在用户低频访问的时间(如晚上10点后)进行部署,但由于数据结构变更、配置项变更导致的不兼容问题还时有发生。
高可用工具建设
总结高可用工具建设过程,基实质在于“运维能力”的建设。或者会说,服务的Fail-Over能力应该算到设计里吧,但是随着DevOps的深入,这两个界线也日益模糊, 无论怎么说,在运维的时候也需要能力探测到Fail-Over的发生。
受篇幅所限,这里仅谈方案。
监控工具
对于云平台来说,有效的监控工具包含:
- 服务关键指标监控:主要收集CPU、内存、流量、TPS等基础信息;
- 服务异常监控:主要为服务指标(例如访问量)并没有标准的告警阈值,必须对其变化情况进行跟踪分析,并在异常剧烈波动时告警;
- 日志分析监控:主要为日志中可以发现很多次运行时问题,要从程序日志中分析程序的错误情况,提早发现一些从外部运行指标无法观察到的问题;
- 客户端监控:采集客户端上的请求数据和页面加载数据,通过地域、服务、产品等维度来对该数据进行分析其中的延时和错误情况,并在出现剧烈异常波动时发出告警。
对于监控平台的建设,可以采用open-falcon ,支持基础的数据采集、告警以及dashboard,有定制需求,也可以方便的进行扩展。
对于日志系统的建设,可以采用ELK , 该系统由ElasticSearch、Logstash和Kiabana三个开源工具组成,支持集中化日志管理、统计、检索。
对于客户端监控的建设,笔者所在的公司采用自研处理,自然有实用的商业工具可以选择,如腾讯、阿里、华为等云平台均有推出类似产品(产品较多,就不一一说明了,包含Android/iOS端、以及WEB端的性能、日志上报等)。由于客户端的主要涉及数据的整合能力,因此采用自研方案,一般包含:网络请求、地域分析、启动时间、崩溃、卡顿、设备统计、日志等功能。
检测工具
主要由:
- 代码扫描:主要是通过静态代码分析,确认代码健壮性,主流的工具为:SonarQube;
- 拨测工具:简单的做法,可以做个定时任务,跑个python脚本,确认服务是否正常响应。比较正常的做法,可以购买大厂的云拨测工具,享受“分布于全球的服务质量监测点”。
- 混沌工程:infoQ上讨论的比较多,模拟各类的故障查看服务的反应,当然在预生产做的比较多,生产线偶尔也会在凌晨没有访问的时候做一下。一般来说:
- 对于中间件,做法比较暴力些,模拟网络中断、实现重启、主节点重启、CPU负载、慢查询等;
- 对于计算节点(如Tomcat) ,模拟实例重启、实例关闭、CPU负载、请求超时等;
- 对于第三方服务,通过开发框架(没有ServiceMesh,只能要开发框架中嵌入了),嵌入API阻断能力,进行模拟(笔者所在的公司使用该功能验证关键链路SDK是否有做Fail-Over能力);
- 全链路压测:在线上环境进行压力测试;
- 简单场景下,可以直接在线上环境上负载测试,测试完成后完成数据的清理工作,即可;
- 一般的线上产品数据比较复杂,难于清理,此时就要做在流量级别上识别出压测流量有,将压测数据写入影子表、影子库,对于第三方调用时,可能需要Mock请求,进行模拟响应;
对于上述工具的整合:
- 针对可自动化部分,将结果接入监控平台,报障告警能力;
- 对于手动分析部分,则将问题记录BUG系统,当BUG处理;
检测工具为主动发现系统问题的一种手段,很遗憾的是,这里谈到的内容,很少、或者没有现成的工具,这里不展开讨论了。后继做为专题单据写文章发吧。这里推荐一些文章:
定位工具
故障的定位,涉及:
- 日志工具,上述介绍过,这里特别说明的时,由于调用关系比较复杂,笔者所在的公司自研日志工具,将服务间调用的输入、输出参数都记录下来,以便故障时查询分析;
- 链路跟踪,用于解决服务之前调用的定位,一般采用Pinpoint , 当然也有用Zipkin , 但后者需要定制的比较多;
恢复工具
故障的恢复,一般由:
- 故障自动恢复能力:
- 针对计算节点(如Tomcat),支持自动扩容(条件为TPS超阀值),重启(条件为CPU等资源超阀值),一般来说,采用K8S来管理计算节点的情况下,这些能力相当于即得的;
- 故障处理能力,当人工介入后,一般会采用如下手段:
- 限流、降级、熔断,API网关的标配了;
- 应用预案相关的工具,涉及数据的备份、恢复,以及服务自身提供的相关的能力 ;
注:
- 有人可能认为有扩容,也要有缩容,但是对高可用来说,缩容是有损的,一般不做自动化处理;
变更工具
对于变更管理做的工具,主要是预防类的,主要为:
- 蓝绿部署:服务上线前验证,采用K8S管理的场景下,做集群切换即可;
- 配置项管理:分布式配置管理,常用用的SpringBoot,当然还有携程的Apollo、阿里的Nacos等;
- 数据库管理:数据库的升级是一个难题,目前主要做备份、恢复工作,无现成的工具可用(一点点的数据不算,这里主要的数据成规模的场景);
其它工具
以上的讨论,并没有涉及到一些管理工具,如:
- BUG管理、项目管理,大家应该比较熟悉,如禅道;
- 线上故障管理,也可以用BUG管理进行记录吧,笔者公司按流程做定制做开发;
- 信息公司,采用wiki之类的工具;
高可用的架构
一个基础的微服务架构,如下图所示 :
基于上述的基础架构,讨论高可用构架的建设。基础如下:
热备、双活、扩容
对于双活的建设,比较壕的做法:
- 双机房、异地多活;
当然这种的建设费用比较高,暂时不讨论了。一般来说:
- 对于API网关,有Keep-Alive等现成的工具可用;
- 对在API网关后的服务(Tomcat等Web容器),基本都是即得的(API网关默认能力);
- 特别说明的是,对Tomcat等计算节点的扩容,如果部署在K8S中,也几乎是现成的;
- 对于第三方中间件,如MySql、Mongo等,可参考相应的部署说明;
另外,这要单独说明的是,对于要支持热备、双活、扩容的业务系统,需要在设计时注意:
- 业务系统要做成无状态的,有些开发人员,采用Guava Cache、Caffeine、Encache做缓存,且未处理多实例间的数据同步问题,就无法满足要求了;
- 业务系统的标识,采用UUID,如果一定要使用自增型的整型的话,建议使用数据库中的自增ID;如果使用本地的自增整数的话,也是无法满足要求的;
- 尽量小用事务,如果一定要使用的话,采用合适的分布式事务锁;
缓存、及静态化
对于微服务构架来说,缓存的建设是从客户端开始的:
- 客户端(手机端、Web端):都可以利用本地的缓存体系,如浏览器的LocalStorage、移动端的SQLite等;
- 对于有条件的厂商,可以考虑将API请求接入CDN,动态CDN服务费用比较高,阿里、网宿、腾讯等CDN厂商都有提供;
- 在API网关层,也可以参考HTTP的协议,开启HTTP协议的缓存能力;
- 在服务端,一般做二级缓存, 这边介绍J2Cache ,重要是的实现的一级缓存的同步问题;
对于静态化的建设,方案相对复杂。笔者所在的公司基于无头浏览器开发了一个站点静态化的方案,后继有机会单独拿出来写。
Fail-Over、降级
如果是一个多活的系统,基本上都支持 Fail-OVer的。在笔者所有的公司的Fail-Over中,采用一种极端的:
- 将相关静态的配置数据、业务数据, 定时的生成静态文件,并将其上传到内容文件中,当原系统出问题时,可以临时的获取静态文件数据,以做应急使用。
当然这个方案,只解决读的问题,而相对来说变更不频繁的数据。对于真正的系统来说,适用性相对有限了。
对于 Fail-Over、降级,在实践中,都要求在业务系统中提供开发的SDK。当然这么做对于后继也会产生一些升级维护的问题,
一些反馈
关于高可用与高并发
从理论上来说,高可用与高并发是两个维度的东西:
- 高可用,是指在一定条件下(包含一定的并发条件下)的可用性,通过SLA进行度量;
- 高并发,是批在一定时间内处理的的更多的请求,通过TPS等指标进行度量;
从技术手段上来说,这两个主题存在可复用的技术的,如:缓存、CDN等,但具体使用过程中是存在一定的区别的。例如在缓存的应用上,高可用更多的需要支持Fail-Over的能力,而高并发更多的需要支持高速读写能力。