阿里如何应对亿级高并发大流量?如何保障高可用和稳定性!

作者:丁浪,目前在创业公司担任高级技术架构师。曾就职于阿里巴巴大文娱和蚂蚁金服。具有丰富的稳定性保障,全链路性能优化的经验。架构师社区特邀嘉宾!

阅读本文,你将会收获: 

  1. 高并发、大流量场景的常见问题和应对手段

  2. 知名互联网公司的高可用架构和稳定性保障体系

前言

我从业之初便开始扮演“救火队员”角色,经常去线上执行“救火”、止损、攻关等应急工作,再通过分析、推理、验证…抽丝剥茧”的找出背后的根本原因,仿佛自己是个“经验丰富、从容冷静、思维缜密”的侦探。

以前我一直认为线上问题定位、分析处理能力是架构师的“看家功底”并常引以为傲。

但最近这两年我开始思考,其实防火”比“救火”更重要,正如一句古话上医治未病,中医治欲病,下医治已病”。下面我将为大家分享稳定性治理经验和阿里的稳定性保障体系。

稳定性治理的常见场景

突发大流量

 

相信大家对上图并不陌生,尤其在刚刚过去的双11、双12中。这是电商大促场景中执行了最常用的自动预案 - “限流保护”,并非很多朋友说的“宕机”、“崩溃”。

 

限流”是应对高并发或者突发大流量场景下的“三板斧”之一,不管是在电商大促、社交媒体突发热点事件(例如:遇到“知名女星出轨”),还是在常态下都是非常有必要的保护手段。本质上就是检查到当前请求量即将超出自身处理能力时,自动执行拒绝(或者执行请求排队”),从而防止系统被彻底压垮。

 

不稳定服务

讲到限流”,那就不得不提另外一板斧降级”。除了我们之前所提到的 “开关降级”(关闭次要功能或服务)、兜底、降低一致性等之外,在技术层面最常用就是自动熔断降级”限流”是为了防止大流量压垮系统,而熔断”是为了防止不稳定的服务引发超时或等待,从而级联传递并最终导致整个系统雪崩

 

如图所示,假设服务D此时发生了故障或者FullGC等,则会导致上游的服务G、F中产生大量等待和异常,并级联传递给最上游的服务A、B。即便在服务G、F中设置了“超时”(如果没有设置“超时”那情况就更糟糕了),那么也会导致线程池中的大量线程资源被占用。如果服务H、I和服务G、F在同一个应用中且默认共用同一个线程池,那么也会因为资源耗尽变得不可用,并最终导致最上游的服务A和服务B整体不可用,全部链路都将异常,线上核心系统发生这种事故那就是灾难。

假如我们在检查到服务G和服务F中RT明显变长或者异常比例增加时,能够让其自动关闭并快速失败,这样H和I将不会受影响,最上游的服务A和服务B还能保证“部分可用”。

举个现实生活中更通俗的例子,当你们家的电器发生短路时空气开关会自动跳闸(保险丝会自动 “熔断”),这就是通过牺牲你们家的用电而换回小区的正常供电,否则整个线路都会烧毁,后果会不堪设想。

所以,你得结合实际业务场景先找出哪些接口、服务是可以被“降级”的。

架构单点

 

这个事件大概发生在2015年,被载入了支付宝的“史册”,也推动了蚂蚁金服整体LDC架构(三地五中心的异地多活架构)的演进。

异地多活架构

  1. 突破单机房容量限制

  2. 防机房单点,高可用


内建质量

根据以往的经验,60%以上的故障都是由变更引起的,请牢记变更“三板斧”:

  1. 1.     可回滚/可应急

  2. 2.     可灰度

  3. 3.     可监控

 

预防质量事故的常用手段:

  1. 做好分析、设计、评审,容量评估,规避风险

  2. 制定规范,控制流程,加入代码扫描和检查等

  3. 阉割做好Code Review

  4. 测试用例覆盖(通过率、行覆盖率、分支覆盖率),变更全量回归

  5. 尽可能的自动化,避免人肉(易出错),关键时刻执行double check

 

感兴趣的读者可以参考我之前发布在“架构师社区”的文章《关于故障和稳定性的一点思考》,里面有一些实践经验和思考,这里不再仔细展开。

  

高可用架构的基石--稳定性保障体系

从故障视角来看稳定性保障

稳定性保障的核心目标

  1. 尽早的预防故障,降低故障发生几率。

  2. 及时预知故障,发现定义故障。

  3. 故障将要发生时可以快速应急。

  4. 故障发生后能快速定位,及时止损,快速恢复。

  5. 故障后能够从中吸取教训,避免重复犯错。

 

仔细思考一下,所有的稳定性保障手段都是围绕这些目标展开的。

稳定性保障体系

 

 

 

上图涵盖了稳定性体系的各个方面,下面我来一一讲解。

应用架构稳定性

应用架构稳定性相对是比较广的话题,按我的理解主要包括很多设计原则和手段:

  1. 架构设计简单化。系统架构简单清晰,易于理解,同时也需要考虑到一定的扩展性,符合软件设计中KISS原则。现实中存在太多的过度设计”为了技术而技术”,这些都是反例,架构师需懂得自己权衡;

  2. 拆分。拆分是为了降低系统的复杂度,模块或服务自治”,符合软件设计中单一职责”原则。拆分的太粗或者太细都会有问题,这里没有什么标准答案。应该按照领域拆分(感兴趣同学可以学习下DDD中的限界上下文),结合业务复杂程度、团队规模(康威定律)等实际情况来判断。可以想象5个人的小团队去维护超过30多个系统,那一定是很痛苦的;

  3. 隔离。拆分本质上也是一种系统级、数据库级的隔离。此外,在应用内部也可以使用线程池隔离等。分清“主、次”,找出“高风险”的并做好隔离,可以降低发生的几率;

  4. 冗余。避免单点,容量冗余。机房是否单点,硬件是否单点,应用部署是否单点,数据库部署是否单点,链路是否单点…硬件和软件都是不可靠的,冗余(“备胎”)是高可用保障的常规手段;

  5. 无状态、一致性、并发控制、可靠性、幂等性、可恢复性…等。比如:投递了一个消息,如何保障消费端一定能够收到?上游重试调用了你的接口,保证数据不会重复?Redis节点挂了分布式锁失效了怎么办?… 这些都是在架构设计和功能设计中必须考虑的;

  6. 尽可能的异步化,尽可能的降低依赖。异步化某种程度可以提升性能,降低RT,还能减少直接依赖,是常用的手段;

  7. 容错模式(上篇文章中有介绍)

 

我在团队中经常强调学会面向失败和故障的设计”,尽可能做一个悲观主义者”,或许有些同学会不屑的认为我是“杞人忧天”,但事实证明是非常有效的。

从业以来我有幸曾在一些高手身边学习,分享受益颇多的两句话:

出来混,迟早要还的;

不要心存侥幸,你担心的事情迟早要发生的;

 

上图是比较典型的互联网分布式服务化架构,如果其中任意红色的节点出现任何问题,确定都不会影响你们系统正常运行吗?

限流降级

前面介绍过了限流和降级的一些场景,这里简单总结下实际使用中的一些关键点。

以限流为例,你需要先问自己并思考一些问题:

  1. 你限流的实际目的是什么?仅仅只做过载保护?

  2. 需要什么限流策略,是“单机限流”还是“集群限流”?

  3. 需要限流保护的资源有哪些?网关?应用?

  4. 水位线在哪里?限流阈值配多少?

同理,降级你也需要考虑:

  1. 系统、接口依赖关系

  2. 哪些服务、功能可以降级掉

  3. 是使用手工降级(在动态配置中心里面加开关)还是自动熔断降级?熔断的依据是什么?

  4. 哪些服务可以执行兜底降级的?怎么去兜底(例如:挂了的时候走缓存或返回默认值)?

 

这里我先卖下关子,篇幅关系,下篇文章中我会专门讲解。

 

监控预警

 

上图是我个人理解的一家成熟的互联网公司应该具备的监控体系。

前面我提到过云原生时代可观察性”,也就是监控的三大基石。

这里再简单补充一下 “健康检查”,形成经典的“监控四部曲”: 

关于健康检查,主要就分为服务端轮询”客户端主动上报”2种模式,总的来讲各有优缺点,对于类似MySql这类服务是无法主动上报的(除非借助第三方代理)。需要注意的是传统基于端口的健康检查很难识别进程僵死”的问题。

提到监控那就不得不提Google SRE团队提出的监控四项黄金指标:

延迟:响应时间

流量:请求量、QPS

错误:错误数、错误率

饱和度:资源利用率

类似的还有USE方法,RED方法,感兴趣的读者可以自行查阅相关资料。

 

云原生时代通常是应用/节点暴露端点,监控服务端采用pull的方式采集指标,当前比较典型的就是Prometheus监控系统,感兴趣的可以详细了解。

当然,以前也有些监控是通过agent采集指标数据然后上报到服务端的。

 

除了监控自身,告警能力也是非常重要的。告警的阈值配多少也需要技巧,配太高了不灵敏可能会错过故障,配太低了容易“监控告警疲劳”。

强弱依赖治理

这是网上找的一张“系统依赖拓扑图”,可见面对这种复杂性,无论是通过个人经验,还是借助“链路跟踪工具”都很难快速理清的。

何为强弱依赖

A系统需要借助B系统的服务完成业务逻辑,当B挂掉的时候会影响A系统中主业务流程的推进,这就是强依赖”。举个例子:下单服务依赖“生成订单号”,这就是“强依赖”,“扣库存”这也是 “强依赖”;

同理,当A依赖的B系统挂掉的时候,不会影响主流程推进,那么就是弱依赖”。例如:购物车页面中显示的库存数是非必须的;

 

如何梳理出这种强弱依赖,这个在阿里内部是有专门的中间件可以做的,目前开源社区没有替代品,可能就要结合链路跟踪+个人的经验,针对系统级,接口级去做链路梳理。我们重点关注的是 “强依赖”,而“弱依赖” 通常是可以执行容灾策略的,例如:可以直接降级掉,可以返回为空或者默认值、执行兜底等; 

总结出来关键有几点:当前业务功能/应用/服务、依赖的服务描述、依赖类型(比如:RPC调用),峰值调用量、链路的流量调用比例、强弱等级、挂掉的后果等。

容量规划

 

容量规划是非常重要的,无论是成本控制还是稳定性保障都需要。否则压根不知道需要投入多少资源以及资源投入到哪里。需要了解系统极限水位在哪里,再推算出合理的阈值”来做好过载保护”,这也是执行是限流、降级等预案体系的关键依据和基础。

 

第一阶段:主要依靠经验值、理论值等来预估的,或者是靠“拍脑袋”的。

前几年资本市场情况比较好,互联网公司比较典型的现象:老板,我需要买100台服务器,50台跑应用,20台跑中间件,10台做数据库…预计可以扛住日均1000W访问量,每天100W订单…

靠谱一点的人还能扯出 “MySql并发连接数在几core几G大概能到xxx”、 “Redis官方称可以达到10W TPS”之类的参考值,这种至少听起来还有那么一点道理。不靠谱的人呢。那可能就真是瞎说的一个数字,或者会说“我上家公司就用了这么多支撑的”,其实纯靠拍脑袋的。

总之,这都是很不靠谱的。会造成资源分配不合理,有些浪费而有些饥荒。

 

第二阶段:通过线下压测手段来进行。线下压测通常是压测的单接口、单节点,压测结果可以帮助我们了解应用程序的性能状况、定位性能瓶颈,但是要说做整体的容量规划,那参考价值不大。因为实际情况往往复杂太多,网络带宽、公共资源、覆盖场景不一致、线上多场景混合等各种因素。根据木桶短板”的原理,系统的容量往往取决于最弱的那一环节。正所谓差之毫厘,失之千里”

 

第三阶段:通过线上单机压测来做。比较常见的手段有:线上引流、流量复制、日志回放等。其中线上引流实施起来最简单,但需要中间件统一。通过接入层或服务注册中心(软负载中心)调整流量权重和比例,将单机的负载打到极限。这样就比较清楚系统的实际水位线在哪里了。

第四阶段:全链路压测,弹性扩容。

这个是阿里首创的,目前很多公司在效仿。属于是业务倒逼技术创造出来的手段。全链路压测涉及到的内容会比较多,关键的步骤包括:

  1. 链路梳理

  2. 基础数据准备、脱敏等

  3. 中间件改造(透传影子标,软负载/消息/缓存/分库分表等路由,建立影子表)

  4. 建立压测模型、流量模型、流量引擎

  5. 预案体系的检查

  6. 执行压测,紧盯监控告警

  7. 数据清理

 

对业务开发团队同学来讲,关于链路梳理、流量模型的评估是其中最重要的环节,全链路压测就是模拟用户真实的访问路径构造请求,对生产环境做实际演练。这里我以大家熟悉的购买电影票的场景为例。如下图,整个链路中业务流量其实是呈漏斗模型”的,至于每一层的比例是多少,这个第一就是参考当前的监控,第二就是参考历史数据去推算平均值了。

漏斗模型推演示例: 

可以看出每一层(不同应用、不同服务)所需要承载的真实流量不一样,负载也是不一样的。当然,实际场景更复杂,实际情况是多场景混合并行的,A用户在拉排期的时候B用户已经在锁座了…

 

我们要做的,就是尽可能接近真实。还有最关键的一点要求:不能影响线上真实业务。这就需要非常强的监控告警和故障隔离能力了。

 

关于系统容量和水位标准,这里给大家一个建议参考值:

 

水位标准:单机房部署水位应在70%以下,双机房部署水位应在40%以下

单机水位:单机负载 / 单机容量

集群水位:集群负载 / 集群容量

理论机器数:实际机器数 *(集群水位 / 水位标准)

 

为什么双机房是40%?一个机房故障了流量全都切到另外一个机房去,要确保整体不受影响,不会被压垮。

预案体系

电影片段中 “检查到有未知生物入侵地球,联合国宣布启动进入一级戒备,马上启动宇宙飞船达到现场” ,“已经了解清楚,并按协议执行驱逐指令,目前已经离开” … 这就是典型的预案体系。触发条件、等级、执行动作、事后情况都非常清晰,整个过程还带有闭环的(当然这片段是我YY出来的)。

前面我讲过“面向失败的设计”,就是尽可能的考虑到各种异常场景和特殊情况。

这些零散的“知识点”,还有日常的一些复盘的经验都可以作为日后的预案。

当然,前面我们讲过的限流、降级等应急手段,容错模式也是整个预案体系中非常重要的。预案积累的越丰富,技术往往越成熟。

 

总的来讲,预案的生命周期包括:

从大的层面又可以分为:

  1. 事前制定和完善预案

  2. 日常演练预案

  3. 事中统一指挥,收集数据,决策并执行预案

  4. 事后总结并继续完善和改进预案

  

当然,这里说明下,有些预案是达到明确的触发条件后自动执行的,有些是需要依赖人工决策然后再触发执行的。这里我给一个简单的demo给大家参考。

 

线上演练

正所谓 “养兵千日,用兵一时”。现实生活中的“消防演习”就是一个好例子,否则时间久了根本不知道灭火器放在哪里,灭火器是怎么打开的?打开后还能喷出泡沫来吗?对应到我们技术领域也是一样的,你怎么知道你的预案都是有效的?你怎么保证on call值班机制没问题?你知道监控告警是否真的很灵敏?

在阿里内部不管是大促还是常态,都会不定期来一些线上演练。在蚂蚁内部每年都会有红蓝军对抗演练”,这是一种非常好的以战养兵”的做法。

先看一张关于故障画像的大图,这里列举了典型的一些故障场景,大家不妨思考下如何通过故障注入”来验证系统的高可用能力。

简单总结故障演练主要场景和目的:

  1. 预案有效性、完整性

  2. 监控告警的准确性、时效性

  3. 容灾能力测试

  4. 检查故障是否会重现

  5. 检查on call机制,验证突发情况团队实际战斗能力

 

混沌工程”是近年来比较流行的一种工程实践,概念由Netflix提出,Google、阿里在这方面的实践经验比较丰富(或者说是不谋而合,技术顶尖的公司大都很相似)。通俗点来讲就是通过不断的给现有系统“找乱子”(进行实验),以便验证和完善现有系统的高可用性、容错性等。

引用一句鸡汤就是:杀不死我的必将使我更强大”

混沌工程的原则:

 

 

系统成熟度模型: 

面向故障/失败的设计更是一种技术文化,应该在团队中大力推广。

小结

本文我主要讲解了稳定性治理的常见手段,稳定性保障体系。其中涉及到的知识、手段、内容都非常多。限于篇幅的关系,不可能每一项都特特别细致。还需读者慢慢消化,更重要的是好好思考现状并努力改进,也欢迎留言讨论。

如有收获,点个在看,诚挚感谢

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/312476.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

动手造轮子:写一个日志框架

动手造轮子:写一个日志框架Intro日志框架有很多,比如 log4net / nlog / serilog / microsoft.extensions.logging 等,如何在切换日志框架的时候做到不用修改代码,只需要切换不同的 loggingProvider 就可以了,最低成本的…

【C】@程序员,我们送给你一个成熟的Excel导入导出组件

程序员的显著特点有一天跟一位同事跟我闲聊,讨论起过去若干年软件行业的感受,他问了个问题:你觉得一个好的软件工程师最显著的特点是什么?我想了一会,说:大概是坐得住吧。某种意义上来说,在互联…

SummerBoot,将SpringBoot的先进理念与C#的简洁优雅合二为一

哈哈哈哈,大家好,我就是高产似母猪的三合,好久没写博客了,因为最近几个月在不断的加班,加班时长平均每个月120小时以上。今天是2020年的第一天,作为一条程序汪,觉得不做点啥好像对不起这个特别有…

C#刷遍Leetcode面试题系列连载(6):No.372 - 超级次方

点击蓝字“dotNET匠人”关注我哟加个“星标★”,每日 7:15,好文必达!前文传送门:C# 刷遍 Leetcode 面试题系列连载(1) - 入门与工具简介C#刷遍Leetcode面试题系列连载(2): No.38 - 报数C#刷遍Le…

使用 Postman 测试你的 API

使用 Postman 测试你的 APIIntro最近想对 API 做一些自动化测试,看了几个工具,最后选择了 postman,感觉 postman 的设计更好一些,我们可以在请求发送之前和请求获取到响应之后都可以自定义脚本,很灵活。而且 postman 的…

使用 postman 给 API 写测试

使用 postman 给 API 写测试Intro上次我们简单介绍了 使用 postman 测试 API,这次主要来写一些测试用例以检查请求的响应是否符合我们的预期以及如何使用脚本测试使用 postman 内置的随机变量postman 内置的有一些产生随机值的变量,在发送请求时随机生成…

ASP.NETCore编程实现基本认证

HTTP基本认证在HTTP中,HTTP基本认证(Basic Authentication)是一种允许浏览器或其他客户端程序使用(用户名,口令)请求资源的身份验证方式,不要求cookie,session identifier、login page等标记或载…

计算机原理(计算机系统漫游)

计算机五大组成部件:运算器(ALU),控制器,存储器,输入部件,输出部件 1.控制器 2.运算器 逻辑运算(判断事物的对与错) 数学运算(11) 控制器运算器中央处理器(CP…

使用ASP.NET Core 3.x 构建 RESTful API - 4.2 过滤和搜索

向Web API传递参数数据可以通过多种方式来传给API。 Binding Source Attributes 会告诉 Model 的绑定引擎从哪里找到绑定源。 共有以下六种 Binding Source Attributes: [FromBody] 请求的 Body [FromForm] 请求的 Body 中的 form数据 [FromHeader] 请求的 Header […

360浏览器linux版本_360安全浏览器崩溃解决方案

360安全浏览器崩溃解决方案方案一:打开360安全浏览器,按键盘上的F1调出浏览器医生界面,点击一键修复即可。如图所示:方案二:360浏览器打开了太多标签占用内存,并且随着浏览器开着的时间越长,占用…

.NET 开源软件开发BIM工具包xBIM

一、xBIM 简介BIM(Building Information Modelling)建筑信息模型,xBIM(eXtensible Building Information Modelling)可扩展的建筑信息模型。它是一个.NET 开源软件开发BIM工具包,支持BuildingSmart数据模型…

2019(dotNet全栈开发)公众号回顾

2019年已经过去,人口红利已经逐渐消失,也许这是这10年互联网史上最糟糕的一年,也可能这是未来10年互联网史上最好的一年关于公众号,我其实很早就开始注册了,只是一直没怎么运营(ps:不知道怎么推…

CSS padding margin border属性讲解

把所有网页上的对象都放在一个盒(box)中 ,设计师可以通过创建定义来控制这个盒的属性,这些对象包括段落、列表、标题、图片以及层。 盒模型主要定义四个区域: 内容(content) 内边距(…

【实战 Ids4】║ 客户端、服务端、授权中心全线打通!

1、经过元旦两天的全力整改,终于在这新的一年,完成了我的布道生涯的第一个大步走 —— 那就是客户端(VUE)、服务端(ASP.NET Core API)、授权中心(IdentityServer4)的大融合&#xff…

补丁 检测系统_大云制造 | BCLinux For ARM64 V7.6操作系统正式发布

友情提示:全文3000多文字,预计阅读时间10分钟概述大云企业操作系统(BC-Linux,BigCloud Enterprise Linux)是中移(苏州)软件技术有限公司借助开源社区优势,通过定制化手段研发的高性能、安全可靠、自主可控的企业级Linux操作系统。…

告别2019,写给2020:干好技术,要把握好时光里的每一步

本文来自:长沙.NET技术社区 邹溪源不知不觉,一晃年关将近,即将翻开2019,进入新的一页。(本文写于2019年12月27日)这周已经在朋友圈看到了来自公众号《恰同学少年》《Edi.Wang》和《吃草的罗汉》几位老师写下…

单片机课程设计数字心率计_如何选购合适的PH计

聚舟供应的PH计PH计已经被广泛应用于各个行业,如工业、电力、农业、医药、食品、科研和环保等领域,在酸碱值检测时必不可少的,那么该如何选购呢?聚舟销售的PH计也有多种样式与型号,各种型号都供应充足,欢迎…

cd返回上一 git_如何使用Git实现自动化部署你的项目

在开发过程中,我们不可避免的会用到版本控制。你可能对 Git 和 SVN 有所了解。一开始基本都是在用SVN,现在可能都进化到用Git了吧,因为SVN缺点比较多。这里就不过于多的介绍Git的优点了。不知道大家一开始是怎么使用 git 进行开发的&#xff…

在Asp.Net Core中使用ModelConvention实现全局过滤器隔离

从何说起这来自于我把项目迁移到Asp.Net Core的过程中碰到一个问题。在一个web程序中同时包含了MVC和WebAPI,现在需要给WebAPI部分单独添加一个接口验证过滤器IActionFilter,常规做法一般是写好过滤器后给需要的控制器挂上这个标签,高级点的做…