2020 年学到了什么

最近在面试的时候,和面试官说 A 家有比较先进的业务架构和基础设施,被人要求一一列举,一时语塞(这么多东西,我半小时实在给你说不完),才想起来去年本来答应老东家的同事要总结一些两家的业务和基础设施之间的 diff,都鸽了快一年了。看来面试的时候是遭报应了,该还的债总是要还的。

正好去年也没做什么技术方面的总结,从 A 家离职半年有余,这个时间点总结一下去年一整年的学习成果还是稍微有一点必要的,等明年说不定就忘了。

业务

单元化

在前一家公司工作的时候,碰到过 A 家来的人说稳定性问题可以用单元化来解决,所以进了 A 家,单元化也是我重点关注的问题。

单元化的方案原理比较容易理解,用户 id 按照常数做 hash,比如 100,那么在逻辑上将所有业务系统都拆成 100 份(部署单元和逻辑单元有个映射关系,可以根据业务规模再做调整),后续使用 user id 的后两位对 100 求模,决定用户的流量发往哪个单元。

A 家应该是比较早做单元化的,他们会去帮一些比较传统的金融机构做架构改造和咨询,所以本身方案是对外开放的,在阿里云上可以找得到相关的单元化介绍

单元化本身也被称为 set 化架构,或 bulkheads 模式,其本质是通过架构上的设计,消灭了很多高并发场景下难以解决的问题。

我可以举个例子,无状态的系统研发经常会说横向扩展很容易,只要加机器就好了。但他们忽略了一个比较重要的问题,服务粒度的变化和拆分会导致线上的实例数膨胀 -> 进而连接数膨胀,这意味着你不可能无穷无尽地把你的服务拆分下去。如果读者是写 Go 的,你可以认为在优化过的系统中,一条长连接至少也对应一个 goroutine,这个是要占内存的(数量越多,GC、调度的成本也越大)。即使无状态的服务不需要考虑这个问题,在数据库、数据库的 proxy 层也不可能抗得住无穷无尽膨胀下去的长连接。

这些巨头的服务规模一般都比较大,按照之前 A 家的 registry 和 mesh 的公开宣传数据,线上至少有百万级别的 pod。即使除去非核心服务,主链路上的服务有几十万实例也是很正常的。如果不做单元化,每个服务都需要处理海量连接,高并发这种业务无关的问题。

游戏领域的分区和这种单元化稍微有一点类似,不过分区对用户来说并不透明,基本都需要玩家手动选择进入的“大厅”。

单元化的架构改造其实没那么容易,A 家这里能够比较顺利的原因我认为主要有下面这一些:

  • 统一的 api 框架:虽然技术人员众多,但他们内部的框架相对来说是统一的,至少在同一个 bu 内一定是统一的,单元化的 sharding 规则需要在各个模块中都能保持一致,如果每个组一个框架,那这个前提就不太成立了。
  • 稳定性的强需求:每一家互联网公司都在叫唤高可用,但每一家的高可用需求是不一样的,比如很多公司都在讲异地多活,但他们的跨机房专线断掉的话,业务就直接瘫痪了。这种就是典型的假多活。金融相关的公司,国家有很高的稳定性需求,这个糊弄不了。据说服务中断半小时就要去主管部门喝茶了。
  • 基础设施的高投入:这个可以拿上一家公司来做对比,同样的一个比较细分的 inf 方向,在 A 家的人数可能能达到我前一家公司的 4 倍以上。人数优势可以让他们更多地做一些平台上的工作或者更前沿的探索。

这三点对于单元化来说都是必须的,中小规模的公司想要做同样的事情就很难了:

  • 很多公司的技术栈分裂很严重,即使是一点很小的全局改动也要拉上全链路的人撕逼出方案,这种需求三个月到半年看不到产出也是很正常的。不同的组之间可能用的都不是同一个框架,如果是写 Go 的地方,因为造一套自己的框架也不是很难,很多人就倾向于不使用公司的框架,而是自己造。给后续的架构改造留下了巨大的隐含成本。
  • 嘴上都在说稳定性,没出故障的时候大家都是 99.99%,出了故障就变成 3 个 9 了。如果没有强制力来约束,稳定性是个薛定谔问题。比如没有碰到过跨机房专线被挖断这种事情,这些公司不会把处理这种问题当作架构设计的必选项。
  • 有些公司的业务模型是低毛利模型,即使都是对基础设施投入 10%,不同的公司的 10% 差距也很大,现代的软件研发是团队工作,研发人员又不傻,1 个人不可能干得了 10 个人的活儿。

全局的架构改造需要自上而下推动,需要有人主导,有人背锅,整个改造过程也需要不小的成本。如果只是一线的技术人员,看看就好了。

中台

中台的概念最早就是 A 家炒起来的,我在 2016 年左右就在上家公司听到有人讲大中台 + 小前台了。

我们之前做的数据平台本身也要对接多个业务方,在几年的迭代过程中基本上摸清楚了平台建设和前中台合作的基本门道,期间看到很多人在无脑吹,所以当时写过一篇“中台的末路”来引战,顺着当时的评论线索,也看到了其它一些批评中台的声音,可以对这套业务建设的方法论更理性地看待了。

进了 A 家我也重点关注了一些内部的声音,显然 A 家的中台也没有那么神,其它公司在建设和使用中台的时候会碰到的问题,A 家内部也碰得到,这一点倒是不太意外。(这里强调一下,因为我去 A 家不是做业务的,所以这里业务相关的结论是从内部的讨论中得出的结论)。

A 家的中台毫无疑问,还是走在国内前列的,这么多年的持续演进,客观地说,已经是一堆挺先进的平台和开发的方法论了:星环

公司外部看这些理论,都显得有点虚,在内部我仔细地学习了星环的设计思路和开发流程,总结一下,这套业务平台的关键就是将互联网业务的流程进行了很好的可视化沉淀。电商业务的各个方向都被总结成为一套“商业能力”,变成了可以编辑的工作流+扩展点,沉淀到了平台上。

在沉淀之后,非技术人员也能通过这个平台很快地了解各个电商环节的领域知识,做一套新的电商系统的话,和搭乐高积木差不了多少。

如果要修改某个节点的行为,一般通过扩展点来做,这里的扩展点在平台上会告知一个全局唯一的字符串,比如 tmall.business.trade.pay_xxx,对应的模块中只要使用该注解:

@("tmall.business.trade.pay_xxx")
public bool function need_pay(params) {
   return true
}

就可以修改该节点的行为,当然这套设计肯定也是有问题的,我也找到了一篇实际参与 A 家业务开发的人的吐槽,大家低调阅览,不要乱传:中台的问题

里面讲到了中台的协作成本、认知成本和稳定性成本,这些和我早期在中台的末路一文中写的观点也比较类似。

既然我们知道中台沉淀的是工作流、扩展点、平台和界面,那么我们自然可以知道,如果新业务相比以往有颠覆性,那这套方法论自然就不灵了。

比如电商的后来者 PDD,虽然 PDD 看起来是个电商,但其实它本质是一个游戏。在以往沉淀的这些商业能力模板上套出一个游戏,怎么都不可能。

A 家后来推出了新的特价版 APP 也印证了这些结论,这并不是什么反直觉的事情。

再后来 A 家自己的中台策略也做了一些调整,成为了白名单内不可选和白名单外可选的新策略,我认为这些调整还是合理的,符合直觉,也符合类似于市场的发展规律。

互联网公司做架构肯定是为了效率,架构本身成为了瓶颈,问题肯定还是要解决的。

实时计算

A 家本身收购了 flink 的母公司,在云上对外卖流式计算相关的服务,自身对这方面的投入也比较大,之前在某站点上看到人说 A 家比 Google 的流式计算进度还快一些,所以我也特意看了看 A 家的发展情况。

因为有相关项目的核心 committer 和 PMC,所以流框架本身的稳定性是不太用担心的,在线 IDE,SQL 化,这些自然都是实现了的。内部经常可以看到有 youku、高德等 bu 的人写文章讲他们怎么做业务在 stream SQL 上的抽象,看起来平台建的也比较完善了。

这个 SQL 抽象可能很多人还不太理解,下面这张图是从 《one sql to rule them all》这篇 paper 里摘出来的:

因为 Google 的 data flow 论文已经把乱序的流式处理抽象的不错了,对 SQL 扩展来支持流式处理中的 window、event time、watermark 以及各种算子都是顺理成章的,80% 的业务对数据的需求都不是很难,原先用 java、scala 写的计算代码现在可以方便地用 SQL 来表达,保留好给用户去写 UDF 的扩展接口就可以。

有了 SQL 的抽象,其实业务的平台方可以做更多事情,做出一套类似 tableu 或者 saiku 的实时计算版本应该也只是时间问题,不过我暂时还没看到哪家出来宣传他们这样的系统,如果有哪位读者知道有相关的系统欢迎分享~

至少我在 A 家没看到。

和 A 家的这些基础设施相比,前一家还是稍微差了一点。

MQ Schema

在前一家工作的时候,我写过一篇《MQ 正在变成臭水沟》,主要讲的关于 MQ 数据本身没有 schema 和数据倾斜之类问题的校验会导致各种莫名其妙的事故的问题。

进了 A 家之后,我看到 A 家的 MQ Schema Registry 功能也上线没太久,不过核心系统都是 Java,一般业务 domain event 都有 Java 的代码约束(比如一个 xx bean 什么的),应该情况会好一些,内部似乎没太看到过相关的抱怨,估且认为这个问题是已经被解决了吧。

常态化压测

电商促销节搞的特别频繁,春节红包,618 大促,双 11 大促,双 12 大促,再加上一些穿插的莫名其妙的大促,全年有很多时间都被促销和各种活动覆盖,按我观察到的情况,A 家的压测极其频繁。

全链路压测本身不是什么新鲜事情了,虽然针对压测的改造是覆盖到全链路的,但很多公司会碰到压测没问题,但到了流量洪峰还是被打爆的情况,因为压测到洪峰中间一般还会有很长时间的迭代,迭代期间没有 regression 相关的测试,可能会让之前的压测成果付之东流。

在 A 家我体感到的压测几乎就没停过,全年有一半的时间都在不停地压,有专门的团队和相关的 QA 来负责该压测,压测时使用的数据也是依据往年的存档的监控数据来按增长比例发压,相对来说还是比较科学的。

压测平台建设比较完善的话,把主链路上的系统压到快要崩溃(延迟上升,错误增加)时,基本也就自然停了,这时候相关的负责去定位具体问题,再找人尽快解决。

通过压测的常态化,基本上碰上促销都没有什么大问题。不过这种常态化的压测对于一些稳定性不太好的系统是比较折磨人的,所以感觉业务方自己提前搞搞压测预先做优化还是有必要的。否则封线期间去解决问题,压力还是比较大的。

开发军规

这个可能是 Ant bu 的特色,在工位旁边的墙上一般都贴了一张海报《财富编码军规》,常见的业务开发中的规范和问题都被编成了打油诗:

因为没有在外部看到过相关的宣传,这里就不截全图了。。有泄密问题。

业务研发应该都是知道这套规范的,能通过这样的知识输入和培训尽量避免一些编码上的低级失误。

个人感觉里面有一些规范是可以想办法集成到公司的静态分析系统里的,本人不在业务部门工作,所以也不知道是不是已经有一些相关的尝试了。

infra

在离线混部

基础设施部门做的事情目标主要就两个,降本、提效。在离线混部应该最早是 Google 提出的(不确定),现在国内的公司上了 k8s 之后相当于有了个微缩版的 borg,在这上面去做在离线的混部应该就不像以前那么难了。

A 家的方案只是做了一些宣传,不过 2020 的双 11 方案已经在线上跑了。不过腾讯的方案倒是开源了:腾讯的方案

在离线混部主要是为了提升机器的 CPU 使用率,是为了降低公司的 IT 成本。需要考虑这个问题的应该都是巨头,这也算是幸福的烦恼了。

日志无盘化

简单来说就是 Fuse(File System in Userspace) + logtail,具体见这里,让用户的日志做到无盘化,这样因为磁盘问题而导致的写日志 hang 问题会大大改善。

不过我只是个观众。

安全

金融类的业务对安全性有很高的要求,比如我实际参与的可能是 mesh 里的 TLS 开启这种环节,公司内有专门的安全容器项目:katagvisor在 A 家都有落地的场景。

顺藤摸瓜,可以找到 Google 关于零信任基础设施相关的生态的一些介绍,不仅限于我上面提到的这两点:

最近国内出现了一些比较大的公司的代码和数据泄露事件,安全问题后续肯定会被各大公司提上日程认真搞了。

攻防演练

历史上支付宝曾经发生过一次大规模宕机事故:527 事件,所以 527 成为了这家公司的一个重要的时间节点,每年都会有这么一天拉一堆人来进行红蓝攻防演练。

现在这家公司已经可以做到在公众面前直接把网线剪断也不怕挂的程度,所以这种重要事件对于推动公司稳定性向上一个台阶来说有重要的意义。

在开头的时候我们也说过,没有真正演练过的多活是不靠谱的,相关的悲剧在其它公司我也见过很多次了。

红蓝攻防演练除了稳定性问题之外,安全性问题也被囊括在内,如果能够找到系统的漏洞,让别人的系统瘫痪,内部也是有专门的奖励机制的。

mesh

因为我入职主要参与 mesh 项目,这个项目是 Go 编写的,在 A 家部署了大概几十万个实例,应该是业内最大(不是最大,那也是属一数二的)的 Go 系统了,由于 mesh 本身的特性,不同的业务的不同请求特征,导致 Go 编写的 mesh 几乎会碰到所有 Go 编写服务时会碰到的所有类型的问题。举一些例子:

  • CPU 飚升
  • OOM
  • 死锁
  • 内存无法下降
  • goroutine 爆涨

因为实例太多,所以百万分之一概率触发的问题,你每天也会收到几个报警,特别是半夜的报警,拿不到第一时间的现场实在太烦,搞的开发人员怨声载道。

在经过调研和开发后,这些问题都被很好地解决掉了,我也输出了一些相关的文章,这里就不再赘述了。

总结

一年的时间不长也不短,有前沿的场景,会让人成长地更快。

Xargin

Xargin

If you don't keep moving, you'll quickly fall behind
Beijing