羊了个羊又又崩了“一天宕机三次”为什么高并发这么难?

高并发,并不是一个新鲜的话题,全互联网公司为之“费尽心思”多年,仍然无法完全逃脱卡顿、崩溃乃至宕机的宿命。

这不近日,一款名为“羊了个羊”的小程序游戏突然爆火,玩法虽简单,但还是没有扛住无数挑战了 2000 次硬是没有一次把第二关玩过去、还要持以“扶我起来,还能再战 500 回合”斗志的网友带来巨大流量的压力,一日三次宕机时有发生,导致热搜榜接连出现#又双叒叕崩了#的话题。

行业中诸如此类的事件屡见不鲜,譬如,还有不久之前闹得沸沸扬扬的东软集团的核酸系统崩溃事件等等。那么,放眼当下,是否会出现一种方式、一种系统、一种架构可以实现“永不宕机”且建筑属于高并发、高可用、高拓展的乌托邦?

陈皓,或许大家更熟悉他在技术圈的昵称——左耳朵耗子。深耕于互联网和金融架构二十多年的陈皓,先后担任阿里云资深架构师、天猫开发总监、亚马逊高级研发经理、汤森路透基础架构师和高级研发经理,经历过“双 11”、阿里云、AWS、Amazon 仓库预测、实时金融数据发布平台、大规模并行计算等项目和产品研发,他于 2017 年创立了 MegaEase 公司,带着「不改一行代码提升系统的性能和稳定性并支持秒杀」的目标,致力于将云计算(PaaS/SaaS )的那些高可用高并发的分布式技术普及到那些需要对技术自主可控的公司。

近日,CSDN 与陈皓就属于程序员的“三高”(高并发、高可用、高性能)问题进行了深入的探讨,邀请他从自身经历出发,分享“避免不了的宕机事件,那又该如何提升架构的稳定性以及做好防御措施降低损失”的宝贵经验,也希望借此能够为正在加急修复系统的程序员们带来一些启发。

陈皓:算是“误入歧途”。本来是想做个中学的物理或是数学老师的,也许会成为今天的李永乐。但是那时高考结束之后,同学和老师都说我的分数当老师有点浪费了,让我学医或是搞建筑,我一看这两个学科都是要学 5 年,觉得学不动,于是就学了个 4 年的计算机,因为感觉可以在上学的时候玩游戏。

CSDN:随着云计算、大数据、AI 等技术的蓬勃发展,20 年前做架构设计和 20 年后的今天做架构设计,有什么不一样的感受?

陈皓:以前做架构更像是做系统集成,主要是把各种系统拼装在一起,那时只要是把它做出来就好了。

现在做架构除了要做出来,还需要考虑包括运维、工程管理等多方面的事情。当前很多架构都是使用分布式系统,然而这种方式带来的问题就是乱,运维太过复杂,因此需要有一些顶层设计加以支持,如协议规范、中间件使用规范、服务治理规范、日志规范、上线规范、故障处理规范等,而以前虽然需要这些,但并没有这么精细化。除此之外,还要在系统中放入很多关键的调度和观测系统,如流量调度、服务调度、资源调度、数据调度、调用链、指标、健康度等等。

简单地打个比喻:做架构好比是在建设新城市,以前进行架构开发就是在建设城市,建完就结束了;现在不仅仅是要建设城市,还要进行管理和调度城市,让城市运作得更稳定、更经济、更高效。

CSDN:仅在本月,成都核酸检测系统异常、《羊了个羊》游戏宕机等事件频上热搜……从技术维度来看,造成在线系统崩溃可能的原因有哪些?

陈皓:系统其实包括软件和硬件两个方面。抛开一些人为的故意因素不谈,按照正常故障而言,宕机通常源于:

软件到达运行的瓶颈 。常见的情况有: 带宽占满或不足 ,对于不少公司而言,买够足够的带宽,需要花费高昂的费用,因此不少系统采用 CDN 技术,这样即使系统出现崩溃,但是网页都能打得开(比如 12306);还有 应用的 CPU /内存过高 ,以及 数据库或关键中间件处理不过来 ,有单点故障导致系统打不开等等。

工程能力的问题。 造成这一问题的原因是上线前没有进行过相关的性能测 试,亦或是企业内部没有扩容和应急计划, 没有足够的运维工具和手段(如 监控数据不足,没有足够的自 动 化的控制系统 ) , 不 能快速解决问题。 这就好像很多天灾一样,本质就是没有科学的管理,不重 视技术 ,灾难来 了后,才发现很多设计没有到位,甚至都是错的。

陈皓:高并发没有一个具体的数字来衡量,但是跟业务逻辑和应用场景很有关系。

第一种是像 12306 系统、银行、电商等类似的业务场景,这些具备交易逻辑和复杂计算,有强一致性事务,这类的系统是最有挑战的系统,因此调优使用到的技术手段也是非常多的。从我个人经历来谈,2013 年,我在阿里巴巴做“双 11”时,交易业务使用到的服务器大约有 1500 台,当时是阿里第一次做全链路压力测试,性能设置在了每秒 5-8 万笔订单左右。经过几年下来,阿里最近的数据可以做到峰值每秒 60 万单,平时每秒 10 万单。除此之外,我经历过的饿了么系统在 2018 年时,一天有 3000 万笔订单,都集中在中午和晚上两个饭点,而且这是需要实时处理的订单,不过好在这个业务是地域性很强的业务,所以,很容易分库分表,做多活也相对比较容易。

第二种是像微博这样的社交类应用。相较前一种,这种应用通过没有太过复杂的交易逻辑,属于轻应用类,微博可以通过弹性扩容做到百万并发,普通社交类应用实现几万至几十万的 QPS(每秒查询率)也不算太难。这类的系统主要还是通过下面几种手段,一种是在各种环节加缓存,一种是通过异步和最终一致(这类系统基本不需要强一性,丢数据都无所谓),最后是通过 sharding 的方式把用户请求分布式。

第三种是像视频类的应用。像视频类就更简单了,不久前,刘德华的在线 亿人在线,虽然听起来数字非常庞大,但是从技术上来看,视频主要是广播和内容分发,基本没有交互逻辑。因此,用 CDN 这样的分发网络很容易实现几亿人同时在线。以世界杯比赛为例,全世界几十亿的人观看电视直播,这样的高并发早就实现了,因为主要是广播。

第四种是需要保证实时性的在线网游等应用,不过,在线网游通常是需要给玩家分区、分服务器的,这样一台服务只能处理有限的玩家,一般来说也就是几百个玩家,甚至更低。

整体而言,高并发与业务场景息息相关,在实现难易度上,偏交易型的第一种难度最高,其次是社交类,然后是游戏,最后是视频。所以,我们可以看到很多论文或是术语都会提到 transaction,transaction 通常意味着比较大的复杂度。

CSDN:互联网发展至今,虚拟化、分布式已经迭代多轮,为什么还有那么多大规模以及时间长的宕机事件发生?

可以从两个方面进行解析,一方面故障是不可避免的,有人为的故障(人是容易出错的——Human Error)和非人为的故障(机器 Failure)。这些是无计划的停机,还有有计划的停机,如发布新系统、升级维护、更新硬件等。这也是为什么行业中即使部分公司做得再好也只能说自己能做到多少个 9,而非 100% 的主要原因。

当前,我们所能努力的就是尽可能地做到多少个 9,这其中需要很强的技术实力支撑。

另一方面,从分布式架构设计来说,我们认为这个世界上的软件都是有故障的,当故障发生时,大家无非都是希望两个事情:

然而,架构系统也有很多的依赖,如基础设施 DNS、CDN、运营商、机房等等,想要实现稳定,还需要大家一起来实现。

陈皓:我相信一般公司在90%-99%之间,头部公司都是在两个九到三九之间,有技术的努努力可以实现三个九,不过四个九及以上需要耗费大量的人力、财力,对普通公司而言,具有极高的挑战,基本不可能。

五个九的系统,我曾在路透的时候看过,所有的基础硬件(包括电源、光纤、空调、机架、服务器、交换机……)都需要在一个机房里有双份,而且要能防得住不可抗力(火灾,地震,甚至核弹),然后还要租卫星,租专用的光纤甚至专用的海底光缆,还要把欧洲,亚洲,美洲做成多活系统。这应该算是六个九的系统了,着实很花钱。

CSDN:在过往的职业生涯中,你是否经历过比较严重的宕机事件?亦或是在架构研发过程中,最具挑战的一次经历是什么样的?

陈皓:有挑战的东西太多了,无论是做性能调优,还是创新型项目,处处都是挑战。围绕高并发,早期在开发阿里巴巴聚石塔(由天猫携手阿里云、万网宣布联合推出的一个“开放的电商云工作平台”),因为一次升级所有的服务都挂了,所有工程师加班加点,抢修 10 多个小时才恢复回来。

CSDN:有时候像秒杀、双十一等活动,可以是有足够的预期准备时间,但是针对一些突发事件带来的高流量,往往并不可控,系统架构应该在日常做好哪些应急措施,提高系统性能和稳定性,尽量减少损失?

陈皓:这种可以分为两种情况,一种是预期流量(像做活动),可以通过评估、压力测试,做好充足的事前准备。如阿里双 11,提前做好预案。

第二种是非预期的流量。以我曾在路透做金融数据为例,对于一些突发事件,会造成股票交易的高峰,倘若系统出现崩溃,是一件很可怕的事情。因此,平时做性能测试时,除了要高过平时流量来应对高峰,还需要考虑时常。比如平时的流量是 100K/s,那么性能测试时要做到 300K/s 以上。不过,这是有钱的做法。

如果没有钱的话,就要通过云计算的方式,实时扩容,微博就是这样做的,他们可以在 5 分钟内扩 1000 台服务器。最后,如果没有资源了,只能走最极端的手段,即拒绝用户访问,比如在阿里的双 11 就有这样的预案,如果量太大,就先停西部,再停中部,保中心城市和东部,不行就保北上广深等大城市。

这种预案在大公司非常常见,无论是国外的 Facebook、GitHub,还是国内的阿里、腾讯等,这样即使出现故障,造成的后续影响也会比一般公司好很多。

CSDN:2017 年,你创立了 MegaEase 公司,主要是想把云计算(PaaS/SaaS层)的那些高可用高并发的分布式技术普及到那需要对技术自主可控的公司,经过 5 年的发展,MegaEase 发展是否达到您的预期?

陈皓:如果说,我们帮助了想要进步的公司,这个是达到预期的, 因为帮助了他们更新了整个系统架构,降低了很多成本,提升了技术实力。

不过,也还有很多公司是没有帮到,这个还没有达到预期。因为分布式架构、云原生的技术门槛依然很高,为此,我们也想要把这个门槛降得再低一些,包括实施的成本。因此,从去年开始,MegaEase 着重开源建设,并且着手研发一个云原生平台,以及一个知识平台,让用户可以容易地获得云原生的知识以及使用云原生的技术。

一定程度上,可以说云原生本身就是一个比较高的门槛,很多东西需要封装起来,让它变得更简单应用。

CSDN:早期,你曾分享过一句话,“不改一行代码提升系统的性能和稳定性并支持秒杀”,这样的愿景也是不少开发者梦寐以求的事情,那么,是如何实现这一点的?

陈皓:是的,就是不改一行代码做秒杀!请注意,这里指的是秒杀场景。所谓秒杀场景,其本身具有特殊性,比如某个参与秒杀活动的产品,在参与人数达到百万人时,实际的产品数量只有 1000 件。在设计系统架构时,首先得保证系统能够扛住一百万的流量,然后通过一个中间件,如 MegaEase 开发的 Easegress 网关,先是扛住前面整体的流量,然后再将最先参与秒杀的 1000 名用户放进来中奖,随后活动结束。

遵循这样的逻辑,基于开源软件Easegress 就可以做到这一点。使用方法可以参考Easegress在GitHub 上的技术文档:

CSDN:这也是云原生流量调度服务 Easegress 诞生的初衷?相比竞品,Easegress 具有哪些优势?

陈皓:其实行业中有 IaaS 层做资源调度、有 Kubernetes 做服务调度编排、有分布式数据库或 NoSQL 做数据分布式调度,但是缺乏流量调度,而流量又是所有分布式技术根因,是一件非常重要的事。我们觉得这个问题非常重要,于是便开发了 Easegress。

相比业界已有的一些解决方案,Easegress 采用的不是反向代理,而是全功能性的流量网关,它具有流量着色调度和编排、业务扩展等优势,支持多种编程语言,可以应用在秒杀、灰度、服务治理、全链接压力测试、工作流、API 编排、FaaS/Serverless 等场景与工作中。

CSDN:Easegress 采用的是开源的方式,根据当前技术发展的趋势,开源是一种避不开的创新策略,开源为软件架构开发带来了怎样的影响?

陈皓:开源肯定是避不开的。现在所有的公司,或多或少都在用开源软件。这其中包含了几层因素:

围绕开源,可以获得更多的客户和开发者。另外,开源也可以建立技术社区和开发者网络,它是一种能够以最低成本、最容易建立社区的方式,树立品牌宣传。

此外,我也认为开源是唯一一个可以与大公司闭源产品竞争的方式,好比 MySQL 和 Oracle 竞争、Linux 和 UNIX 竞争。尤其对于小型创业公司而言,初创业时的产品很难获得业界信任,但是开源可以让大家清晰地看到产品和技术实力,而且可以省去那些商务流程,技术人员和技术人员直接对话,拓展用户的成本就更低了,这基本是一种互联网的思维方式——产品总是从免费开始的。

CSDN:有些企业做开源可能会存在盲目跟风的趋势,甚至导致开源之后选择闭源,在你看来,企业做开源的正确态度是什么?

陈皓:我觉得是这样的,各个公司开源都有不一样的目的,有的是不得不开源,这类正常是使用了开源软件,在开源协议下也必须要去开源,属于被动开源。还有的是主动开源。然而,开源不是把源代码开放出来就结束,还需要有后续的运行等,开源软件不是由某个公司私有化运作的,而是由社区来运作,像现在 TOC、开源办公室,所做的每一个技术决定都是一群人来做的,而不是这家公司。

CSDN:不少架构师似乎有这样一个共识,“一款好的架构并不是设计出来的,而是进化出来的”,对此,您是否赞同这一观点?

陈皓:一定程度上,这两句话是不冲突的。事实上,好的架构一定是设计出来的,而且还是精良设计的,不然就是系统集成了。

不过,软件设计也是一种 Trade-off (权衡)的取舍过程。随着公司不同时期的发展,不同的阶段有不同的重点,导致 Trade-off 也不一样,处于不断进化过程。因此,我认为这句话应该这么说,“一款好的软件必须是经过精良设计的,精良的设计是不断演化出来的”。

CSDN:构建高可用、高性能、高并发的系统架构多年间,有没有一直在遵循的原则可以与我们分享?

陈皓:这其中涉及的东西太多了,这里我只能笼统简单地说说了,从一些通用的维度来分享:

CSDN:对于架构师而言,现在小公司不谈高并发,大公司入门门槛便是高并发,在程序员向上升级的过程中,他们该如何获取高并发方面的经验,需要具备哪些不可或缺的技能?

陈皓:行业中的技术大佬总要带徒弟,因为他一个人干不了所有事情,正所谓一个篱笆三个桩一个好汉三个帮。因此,问题就是如何成为他们的徒弟?

要想成为技术专家的徒弟,首先自身需要具备一定的潜力,这前提就是需要开发者基础能力过硬,对于高并发开发而言,基础知识包括网络、操作系统、中间件、算法、数据结构等等。在此基础上,剩下的就是积攒经验。

结合我的个人经历来谈,最初从大学毕业开始,我也并没有如今这些经验。记得我曾经入职一家企业,对方让我做业务,但是我并不想做业务,而是想从事系统相关的开发。

在工作的第一天,对方告诉我,如果有什么问题,可以去公司内部的论坛里面提问,会有人来帮你解决问题。后来,我看到论坛的一些板块中,有很多基础性的技术性问题,只有提问,没有人回答。于是,我就把那些问题全部回答了。最终迎来了意外之喜,在入职第一天临近下班时候,我特别想去的那个核心开发团队经理便来邀请我加入他们团队。

因此,只要自身基础知识过硬,就值得别人来带领入门,然后自身再不断学习,不断夯实,就会有成长。

CSDN:你曾分享过「技术的发展要根植于历史,而不是未来」,现在是否还这么认为?当下的开发者该如何跟上技术时代的步伐?

陈皓:可以用“踢足球”来比喻,当踢足球时,我们总是会沿着足球运动的轨迹去跑,而要想跑在球的前面,必须判断足球的走向,你要知道球往哪跑,你就要看足球运动轨迹。技术发展亦是如此,如果要知道往哪里走,你就要看技术的发展轨迹,所以,你要看整个技术发展史,从中归纳总结,要去哪里了。

只要具备以上三点,我认为这个技术就可以全身心地投入进去。否则,建议大家先做观望。

陈皓:其实,云原生时代包含了很多内容,我觉得最好的两本书是《微服务架构设计模式》和《 Designing Data-Intensive Applications》(数据密集型应用系统设计)。除此之外,也建议大家多读读官方文档。

CSDN:毕业之后从国企到在亚马逊、阿里巴巴、汤森路透再到自己创业,这一路走来,对自身无论是从技术上还是管理上,要求都非常高,一直以来,保持持续学习的动力是什么?有什么样的学习方法?

陈皓:首先,学习需要有动力。我最早学习的动力就是害怕失业,因为最初我决定放弃人人眼中的铁饭碗——银行的工作,随后到互联网浪潮中求职,恰遇 2000 年的互联网经济泡沫,很多公司相继倒闭,这也让我产生了很大的落差,当时只有一个想法,“如果最初花费力气做下的决定,再失业,狼狈的跑回家,很多人都准备看你失败的笑话”。所以,那时也有背水一战的感觉,不能失败,必须要去学。

第二个动力就是获得成就感。当学到一定的时候,就会有一定的基础解决一些技术问题,然后别人会给到很多的正反馈,包括创业也是。

其次,在学习方法上,我觉得最重要的是学会掌握信息来源,因为信息源不好的话,其实会有误导性。所以我喜欢看一些英文的资料,然后应 Google 搜索引擎。另外,学习一定要多问为什么,多找最佳时间,多比较技术的优点和缺点(Pros/Cons),寻找最适合自己的。

CSDN:从银行离职,到入职各种不同规模的公司,再到现如今的创业,期间是否有后悔过最初的决定?

陈皓:没有!我觉得这是我迄今为止做的最正确的一个决定,从来没有后悔过!甚至觉得还好当初在 24 岁的时候便做了这个决定。现在只是说如果在 2017 年创业的时候,要是能再早个五六年就好了。

CSDN:作为公司创始人,你现在还会经常写代码吗?可否简单分享一下你的技术栈演进路线?