前一段有个很火的博客,讲的是一家全球流媒体企业的监测系统从Serverless+微服务改成了单体,成本居然降低了90%!这一下子可在网上炸锅了,特别是一些看不惯微服务的、单体应用的拥趸,更是坐不住了。但这并不像吃瓜群众看到的那样,仅仅是“回归”单体应用,或者说大家的关注点都盯着那个成本降低了90%。
大部分人忽略了两件事情:
(1)架构的演进
(2)Serverless First
架构的演进
视频监控系统最早版本确实选择了分布式的架构,主要包含三个组件:
1. 媒体转换服务:把视频转换成“帧”,保存在Amazon S3中。
2. 缺陷检测服务:分析Amazon S3中的视频“帧”,检查是否有缺陷。
3. 通知服务:发现了视频缺陷,发送实时通知。
这个架构的好处是:充分利用了亚马逊云科技的基础设施。Amazon S3帮助进行数据在多个服务之间进行中转,Amazon Step Functions帮助对多个服务进行组合和协调。在Serverless的加持下,每个组件都可以根据流量独立地、自动地扩展。
这个架构非常简单,但简单的架构不一定是单体架构,也可能是Serverless架构,因为亚马逊云科技把复杂的细节都给封装起来了,程序员可以专注业务的开发,可以快速实现,快速进入市场。
但是当流量大了以后,这个架构暴露出了两个问题:
(1) 服务粒度拆分得太细,使用Amazon Step Functions组合起来以后,导致状态迁移次数过多,收费自然就高了。
(2) 使用Amazon S3来暂存视频帧,对数据的存取需要一定的费用,当视频流数量很大时,费用也就相应上升了。
很明显,原有的微服务架构已经不满足需求了,必须进行演进。团队的选择是:把所有的服务都放到一个进程中,部署到一个Amazon ECS中,数据的通信不再使用Amazon S3,而是直接用Amazon ECS的内存。既然在一个进程中,Amazon Step Functions也就不需要了,状态转换带来的费用也就没有了。
当一个Amazon ECS不够用,需要扩展的时候,可以部署多个Amazon ECS。用这种方式,成本降低了90%。
但是很多人没意识到的是,这里只是运行成本降低了90%,开发成本并没有算进去。原来系统用的是Amazon Step Functions,在把微服务架构转换成单体的过程中,自然是不用了,但是Amazon Step Functions承担的协调功能怎么办呢?它内置的重试功能、异常捕获功能怎么办呢?如果出现未处理的异常、运行超时、Socket超时等问题该怎么办呢?
这些问题都需要程序员手工来重新编码实现!
此外使用单体架构,失去了原来Serverless自然拥有的横向扩展的能力,想根据流量对特定微服务进行扩展是不可能了,现在扩展的最小单位变成了AmazonECS,并且团队不得不自己去估算流量,编程实现请求在多个Amazon ECS之间的转发。
架构设计本质上是一种权衡(Trade-Off),不可能存在一种面面俱到的完美架构,一劳永逸地解决问题,架构师的工作就是不断地取舍,根据需求不断演进架构,找到最适合自己的。
这个监控系统的架构就是一个演进的过程,从微服务+Serverless开始,最后由于基于成本的考虑,转换为单体,自己实现扩展,自己管理基础设施,自己开发部分代码。亚马逊的CTO Werner说:构建可演进的软件系统是一种策略,必须用开放的心态来重新审视你的架构。
Serverless First
综上所述,Prime Video监控系统这个案例,实际上就是架构演进的自然结果。现在如果你要构建一个新的应用,不要做某种架构的狂热信徒,不能说这个就好,那个就不好,一切都视情况而定,先保持简单,然后再慢慢演进。但是建议大家:一定要有Serverless First的心态。
原因非常简单,使用Serverless,可以抛弃基础设施维护的负担,把注意力集中在业务实现上,在几天或者几周内快速构建一个系统,推向市场并且获得收益。Serverless是真正地按价值付费,用户使用了你开发的产品,才会产生费用,如果没有流量,根本不会产生费用。
当业务取得成功,有持续稳定的流量,对云上成本很敏感,愿意自己维护基础设施,可以接受增加部分开发工作,这个时候可以考虑进行一些架构调整,比如将工作负载转向容器。这是一种市场导向,业务导向的方法,也是一种更加敏捷的方法。如果在设置虚拟机,容器,软件等方面花费太多的金钱和精力,最后发现产品不是市场所需要的,那将是一种巨大的浪费。
Serverless和EDA(事件驱动架构)是绝配,当你采用它们的时候,会迫使你不断思考,把整个系统变成松耦合的状态,让系统中每个组件都更加独立,互不影响。这也是良好的设计要达到的目标之一。
即使将来要“回归”到单体,或者整个系统一部分用微服务,一部分用单体,之前绝大部分组件代码都可以重用,就像视频监控系统那样,你要做的只是把这些组件放入到一个进程,一个Container中,然后手工编码补充完善那些本来由Serverless内置提供的能力。如果反过来,一开始系统不是松耦合的,再想变成微服务和Serverless,那拆分的代价将会非常之高。
总结
视频监控系统这个案例的讨论是很有价值的,它给我们敲响了警钟,并不是微服务不行,Serverless不行,而是要在合适的时间点,选择合适的架构。
现代应用的架构设计要有Serverless First的心态,不要过多考虑基础设施,而是把注意力集中在业务实现上,迅速推出产品和服务,然后再根据实际需求进行调整,从而实现业务价值的最大化。