对话:一个工程师在蘑菇街4年的架构感悟
苏武,蘑菇街工程师,2012 年加入蘑菇街,经历过数年蘑菇街系统的改造升级。曾负责 2014、2015 年双十一稳定性保障工作,目前主要负责全站稳定性工作。
高可用架构:作为架构师,在蘑菇街的技术演进过程中,最难忘的成长经历或挑战是什么?
苏武:挑战和问题时时刻刻都有,如果说对个人成长最重要的,我觉得有以下两次:第一次是 2014 年,整个蘑菇街从一个机房一夜之间搬迁到了另外一个机房,这两个机房还不在同一个省份,我主导了这个项目;第二次,2015 年的双 11,我主导了系统保障工作。
先谈下第一个项目:蘑菇街机房迁移
我加入蘑菇街之前,一直在做业务系统开发,加入蘑菇街后做的事情就比较杂,之前我对 Java 这一块很熟悉,但运维和基础架构也只是听说过而已。2014 年接到机房迁移这个项目,不得不推着我去了解蘑菇街总体的情况,包括机房、整体架构、系统运维、后端存储、DB、cache、中间系统之前的依赖和前面接入方式等。这个项目前后准备了 3 ~ 4 个月,演练了不下 10 次。通过这个项目,我基本摸清了整个蘑菇街的架构情况。
在这个项目的收获主要有:
知识范围变广了,有机会去了解和思考所有的技术方案与决策。比如在迁移的过程中,曾经出现过开源系统出问题不可服务的情况,在当时这些问题超出了我们当时能够处理的范围。通过这个项目,使得我们重新审视对开源系统的评估和使用。
有机会重新来审视当前的架构,看到了很多做得好和不好的地方。做得好的加以吸收,不好的后面加以改进,我个人后续也参与了部分改进项目。
相当于上了一堂架构平衡艺术的课。架构没有完美,只求在时间、资源、需求三者之间有比较好的平衡。
提升了沟通能力。在沟通这一块,和大多数技术人员一样,我不太习惯和陌生人打交道,会有一定焦虑的心理。但在大型项目中沟通的事情是免不了,经历了这个项目也让我多了沟通的信心。
第二个项目是 2015 年双 11 的系统保障工作
虽然准备了每秒几千单的峰值容量,但由于在 2014 年双 11 和 2015 年的 321 峰值时,系统都有出现过一些可用性问题,所以 2015 年双 11 对技术团队的压力是很大的。
当时在保障的思路上面我们也做了一系列改变。比如 321 之后马上开始服务化的改造,把 PHP 迁移到 Java 上;在 9 月份的时候就开始针对双十一做架构风险梳理,通过业务目标评估系统峰值,主链路上做限流和降级的改造;以及制定高峰期的预案等。
(图:蘑菇街在 2015 年应对双十一的架构,点击图片可全屏缩放)
我个人感受最深的是,以前的架构思路是出现问题,解决问题;现在有了个转变,变成了预先思考在系统上可以做哪些事情,来避免问题的出现。
第一个项目给了我机会去解决问题,跟着问题跑的能力。第二个项目给了我更深层次的思考,改变了跟着问题跑的思考方式,做事情有了前瞻性。
高可用架构:蘑菇街从导购网站转型到电商网站的过程中,遇到的主要技术挑战有哪些?分别是如何应对的?
苏武:遇到的问题及挑战个人认为有以下几个方面。
请求量的压力。在转型的过程中,网站的请求量还是快速往上涨,需要更多的资源去支撑,人和机器都是。
业务复杂性增大。电商网站的业务相比导购来说,复杂度大很多。导购只是等于电商的页面展示层,转型后交易、支付、售后、客服、数据服务等系统都出来了,方方面面都复杂了。
一致性与高可用能力。对应到系统上面,对数据的一致性、系统的稳定性和可用性要求都高了很多。
降低耦合与提高服务化能力。蘑菇街 2013 年开始做电商的时候,我们的架构还是 LNMP 的,开发效率比较高,当然也出现了一些问题。比如所有的代码都在一个工程里面,对数据库的访问也是直接访问表,这样其实系统的扩展性和稳定性都比较差,线上故障也多。
在这个过程中考虑到时间短、人不多、业务需求多等限制,我们做了一些比较简单的改进。
业务垂直拆分。我们将交易和支付这类电商基础的代码从之前的一个工程里面独立出来,变成一个独立的工程,内部使用 HTTP 进行远程调用。
将核心功能服务化。将交易和支付系统的 DB 和 Cache 独立,收敛对其的直接访问,改成通过 HTTP 调用服务接口的方式。
使用更好的硬件提升承载能力。在 DB 这块我们做了硬件的升级,从 SSD 升级成了 PCIE 的存储卡。硬件上的提升给我们赢得了更多的时间去改造系统。
高可用架构:蘑菇街的用户量和访问量经历过爆发式增长,为了保证快速增长下系统的可用性,你们有哪些经验可以分享?
苏武:这几年我们每个月都在增长,访问量相比 2013 年涨了一个数量级,加上业务的复杂性变大,带来的内部系统的调用量更大。
2013 年:LNMP 架构
上面说到蘑菇街 2013 年开始做电商的时候,我们的架构还是 LNMP 的,开发效率不错。但等做完以后马上到双 11,结果当时因为几个慢 SQL,全站出了半个多小时的问题。
过后我们就开始做业务的垂直拆分,包括后面的 DB 和 Cache 都做了,然后在每台 DB 都部署了慢 SQL 的监控工具,如果出现慢 SQL,直接 kill,同时每天也会给对应的开发发送要求优化 SQL 的邮件。
2014 年:服务化与 Tesla
2014 年下半年的时候,就开始开发服务化框架了,这里面的判断如下。
一方面当时我们所有的业务逻辑都在 PHP 里面,这一层非常重,所有的代码都在一个工程里面。到了后面除了几个比较熟悉的开发,都不敢改比较底层的代码。这个时候线上的故障也比较频繁,而且还是那种影响范围广的故障,牵一发而动全身。
另外一个方面是,前面 PHP 机器多了后,打到后端 DB 和 cache 的连接数暴涨,会达到 DB 和 cache 的连接数极限。我们也尝试过在中间加一层 proxy 去解决问题,但新的问题也产生了,DB 的事务怎么办?cache 加了中间层 RT(round trip) 涨了 1 倍。再加上我 们对 PHP 没有那么熟悉,市场上优秀的人很少,感觉再下去就 hold 不住了。
服务化框架是蘑菇街自己研发的,叫做 Tesla。
开源方面有 dubbo 这样优秀的产品,当时为什么选择自研?
支持多语言。虽然会去 PHP,但是需要一个过程。短期内 PHP 还是会存在,所以需要考虑 PHP 端的支持。
长远看,需要支持多机房部署与跨机房调用。需要在稳定性保障和服务治理上接入其他的技术产品,自研会更加方便。
选择开源的产品也需要搞透其实现,有自己的驾驭能力,可能根据特定的业务场景做一些二次开发,这个时候你是贡献给社区,还是走自己的分支?将来社区的新特性是否要合过来?
2015 年:中间件建设
2015 年的时候,分布式数据库中间件和分布式消息系统等都开始研发。
数据库中间件主要是为了进行读写分离和分库分表,消息系统主要是用在了业务解耦和异步化上面。
对于监控这一块,除了基础的机器监控,我们开发了一套可以给业务系统使用的监控产品,业务系统可以按照需要进行不同 metric 的埋点,可以进行聚合统计告警。我们还研发了数据库数据增量产品,主要解决数据变更和离线数据导出等问题。
到这个时间段你会发现,基本上大型网站主流架构必须的技术产品我们都有了。当然电商的特色是每年都有峰值特别高的特殊时刻,为了应对这种峰值,我们在稳定性方面也根据往年一些经验开发了一些系统:
开关平台。在业务系统中埋入开关代码。在高峰期的时候如果系统出现问题,可以直接在开关平台关闭出问题的调用点。
限流降级。系统限流是将服务能力之外的请求快速失败,保证系统不会被打垮;降级是通过统计请求的 RT(round trip) 和 QPS 等,当这些指标触发阈值时短暂的将某个服务降级掉,实现有损服务。限流是前置的,降级则有一个短暂的时间延迟,两者会配合着使用。
高可用架构:随着电商业务越来越复杂,商品种类越来越多,你们在架构设计上如何为未来留有余地?
苏武:我个人觉得应该从两个大的方面去做了一些事情
技术产品的准备,主要的目标是分布式的架构实现,像 Tesla 的研发,解决了服务层的分布式。分布式数据库中间件的研发,提供分库分表功能,解决了大部分的 DB 分布式问题。
业务平台的沉淀,在业务上实现分层架构。举个例子:比如电商应用和电商平台的分层,电商应用更加关注的是上层的业务,怎么去做商品的展现,怎么去做一个活动,怎么去开发一个新的玩法。而电商平台则更加关注业务规则和流程的构建,比如使用优惠券下单流程,支持虚拟商品交易等。比如大促的时候,电商应用可能会有会场、店铺商品页、banner 等形态,到了电商平台这边那他就只关注是否是虚拟商品,有没有用优惠券,折扣多少等。
高可用架构:能否分享一下你们去年应对双 11 的经验?今年在备战过程中会有哪些新的打算?
苏武:去年双 11 是属于蘑菇街服务化改造的过程,当时的状况是,交易的业务平台已经服务化完毕;支付及各类电商应用都还在 PHP 当中,其实还是一个不甚完美的局面。
我们做了几个事情:
1. 架构梳理。技术团队一起梳理当前架构的风险是什么,这个梳理的结果将会指导后面去做什么,会将结果进行分类。
有一类风险是可以通过系统改造消除的,这种可以评估改造的时间点和风险,如果能赶得上双 11 就进行改造;如果不行,则寻求另外的解决方案或者整理处理问题的预案。
还有一类风险是短时间内改变不了的,对于这种问题,重点整理处理问题的预案,如果真的出问题,要求在短时间内去恢复。
2. 系统容量评估。根据业务的目标以及业务的模型和玩法,将业务的数据映射到系统上面,将会得系统链路层面的容量目标。比如 1 秒钟需要支持多少下单,根据这个目标再分解到一个个相关依赖的系统需要准备多少容量。
3. 当知道准备多少容量后,接下来要做的就是去准备容量。这个涉及到一个度量容量的问题。
我们采取的方式是线上的全链路压测方式,用的是线上的真实环境,通过隔离压测数据和线上数据做到数据不污染,但是其他的环境和资源都是一样的,这样压测出来的数据会比较准确。这个压测难度还是比较高的,准备的时间比较长,整个压测链路要打通需要各个团队的配合,双 11 之前全链路的压测压了有 5 轮之多。
4. 讲过前面的压测后,会发现有些系统服务能力有问题,不能达到想要的目标,去改造时间不够,加资源又解决不了问题,这种问题比较让人头疼。大家都听过有损服务,这里我们就做了一个事情,就是去梳理各类系统的依赖关系,并定义如下:
一个系统如果不能提供有损服务,则定义为强依赖,反之为弱依赖。
弱依赖如果有问题,可以通过开关和降级等手段摘掉,依赖于此的系统提供有损服务。
如果是个强依赖,那么无论如何都得想办法去改造,让它提供足够的服务能力。
通过这类梳理,我们发现 80% 以上的都是弱依赖,对这些弱依赖我们植入开关和降级代码,在关键时刻可以启用,以确保整体稳定性。
5. 在用户请求入口,我们也做了限流方案,包括 QPS 限流和根据后端服务反馈的监控数据做的动态限流。限流主要是为了防止流量超出评估的容量,将系统打死。
6. 另外我们梳理了大概几百个预案。这些预案前面讲到了是一些应对问题处理的策略,在全链路压测的时候,在系统高峰期一一做了验证(除了一些极端的预案,如 DB master slave 切换这类没有做),当然在双 11 当天只启用不到 5% 的预案。
今年的调整主要考虑将一些经验和人肉干的事情工具化、平台化,另外也会尝试新的保障方式。
高可用架构:蘑菇街团队及工程师文化是什么样的?你们推崇什么样的做事方式?
苏武:这个问题有点大。我们发展速度很快,需要做一些很有意思的系统,需要解决一些比较有难度的问题,当这些被一一完成后,带来的成就感是非常大的,久而久之就是一种正向循环了。
我们推崇做人简单、开放,做事以技术和数据说话。
高可用架构:在你看来,一位成功的架构师应该具备的最重要的能力和品质是什么?对于未来想要成为架构师的程序员,你有哪些建议?
我个人觉得是解决问题的能力和学习能力。解决问题的能力会让技术广度和深度的成长非常快;而学习能力则是不停找到系统最优解的前提。
有一点需要明确,架构师不是个高大上的活,而是一份要干脏活累活的工作。
架构师需要思考方案,解决问题,实现核心功能。每个人都可以是自己负责的模块或者系统的架构师,在开始实现前多思考、多类比,我该选择哪种方案,选择的理由是什么,优缺点是什么,能不能有更优解?如果前提变了(时间、资源、需求),我会做哪些改变?
另外一点就是,多解决问题。不需要是很高深的问题,碰到问题就去搞明白背后的原因、搞懂原理,经验和知识的就会慢慢积累,自然而然就会成为架构师。
往期精彩文章,点击图片可阅读
微博新兵训练营校长:技术成长四个阶段需要哪方面架构知识?
唯品会RPC服务框架与容器化演进
环信首席架构师一乐:煎饼果子与架构模式
本文由李盼采访,想讨论更多架构设计,请关注公众号获取更多文章。转载请注明来自高可用架构「ArchNotes」微信公众号及包含以下二维码。
高可用架构
改变互联网的构建方式
长按二维码 关注「高可用架构」公众号