Prime Video的这翻言论,其实都源于其技术团队近期所进行的一项实践——当团队将Prime Video从微服务转向整体应用后,不仅提升了其扩展能力,还成功节省了90%的基础设施成本。

撰稿 | 杰承

众所周知,身为全球“云计算一哥”,亚马逊向来是微服务和无服务器架构的追捧者。长期以来,亚马逊也在众多场合表示过对这种“现代化”应用程序最佳构建方式的支持。

然而作为亚马逊旗下元老级别的流媒体平台,Prime Video却在近期发表的一篇博客中否认了老大的这一观点,并提出了“从分布式微服务架构到单体应用的转变,更有助于实现高规模、弹性和降低成本。”

Prime Video的这翻言论,其实都源于其技术团队近期所进行的一项实践——当团队将Prime Video从微服务转向整体应用后,不仅提升了其扩展能力,还成功节省了90%的基础设施成本。

1、选择微服务的初衷

作为一个流媒体平台,Prime Video每天都会向客户提供成千上万的直播流。为了确保客户无缝接收内容,Prime Video需要构建一个监控工具来识别客户所查看的每个流中的质量问题,这提出了极高的可扩展性要求。

对此,Prime Video团队优先考虑了微服务架构所能带来的便利。由于微服务能够将单体应用分解为多个模块,这不仅能解决工具独立开发和部署的问题,还能为应用提供更高的可用性、可靠性以及技术多样性。

在经历了上下的一致认可后,Prime Video选择创建了一个由AWS Step Functions编排的分布式组件的解决方案,这是一个基于状态机和任务的无服务器编排服务,理论上,这将允许团队独立扩展每个服务组件。

图片

在完成一系列迁移工作后,Prime Video的服务最终由三个部分组成,媒体转换器将音视频流发送到检测器的音视频缓冲区;缺陷检测器执行算法,并在发现缺陷时发送实时通知;第三个组件则提供控制服务流程的编排。

2、难以承受的系统开销

但很快,Prime Video便意识到了分布式方法在特定用例中并没有带来很好的效果。最初的解决方案设计使用了无服务器组件的分布式系统,这在理论上而言是快速构建服务的最好选择。

然而当更多流加入到服务中时,扩展受限和成本过高两项问题开始逐渐显现。该架构中的主要扩展瓶颈是使用AWS Step Functions实现的编排管理,由于服务每秒都会在流中执行多次状态转换,这使服务很快达到了账户限制。

除此之外,由于AWS Step按照函数状态转换向用户收费,当需要处理大量流的时候,大规模运行基础设施的开销会变得非常昂贵,所有构建模块的总成本过高,导致Prime Video团队无法大规模接受最初的解决方案。

基于开销问题,Prime Video为了减少昂贵视频的转换工作而建立了一个新的微服务,以将视频分成帧并将图像临时上传到亚马逊简单存储服务(S3 Bucket),并使用AWS Lambda并行处理。然而对S3 Bucket的大量一级调用同样需要支付巨额费用。

3、从微服务迁移到单体架构

无奈之下,Prime Video开始考虑单体的解决方案以降低成本和增加应用的扩展能力,在经历了反复试验后,团队最终决定重建Prime Video的整个基础设施。

当意识到分布式方法在特定用例中无法带来更多好处时,Prime Video选择将应用中的所有组件打包到一个流程中,这成功消除了S3 Bucket作为视频帧中间存储的需求。在此基础上,团队还实现了在单个实例中控制组件编排。

从概念上讲,在保持顶层架构不变的前提下,Prime Video仍然拥有与初始设计完全相同的组件,包括媒体转换器、缺陷检测器及编排。这允许Prime Video团队重用大量代码,并快速迁移到新的架构。

图片

当然,转换为单体架构也给Prime Video提出了新的挑战。在最初的设计中,由于每个检测器都能作为独立的微服务运行,Prime Video能够水平扩展多个检测器。然而在单体架构中,检测器只能在同一实例中运行。

为克服这个问题,Prime Video对服务进行了多次克隆,利用不同的检测器子集对每个副本进行参数化,并实现了在单个实例中控制组件的编排,该解决方案运行在EC2(弹性计算云)和ECS(弹性容器服务)上,且具有一个轻量级编排层来分发客户请求。

图片

最终,将全部服务迁移到整体平台后,Prime Video的基础设施成本降低了90%,并拥有了更强的扩展能力。如今,Prime Video不仅能够同时处理成千上万的音视频流,且仍有能力进行更多的服务扩展。

4、被过度营销的微服务

微服务被过度营销可能是许多问题的根源,medium作者Adrian(前亚马逊云科技可持续发展架构副总裁、前云架构战略副总裁)发文认为,这可能是因为供应商想通过简单的营销信息来销售Kubernetes,即企业需要通过使用Kubernete为一切提供云原生微服务来实现现代化。

事实上,我们看到的是对这种信息的实践上的强烈反差。具有讽刺意味的是,许多企业工作负载是间歇性的、小规模的,非常适合使用Step Functions和Lambda的无服务器优先方法。但如果大型团队则不然,大规模运行的成本是高昂的,仅Kubernetes的复杂性就会让人倍感头疼。

图片

摘自Serverless First(无服务器优先)2019年发布

Prime Video团队的做法被adrian称之为Serverless First的路径,即,构建东西的第一次尝试是与Step Function和Lambda调用结合在一起。重点在于,当你在探索如何构建东西时,在几天或几周内快速构建一个原型是一个很好的方法。然后,他们试图对其进行扩展,以应对高流量,并发现他们的步骤函数中的一些状态转换过于频繁,并且他们在AWS lambda函数和S3之间进行了一些过多的调用。他们能够重用大部分工作代码,将其组合成一个长期运行的微服务,该微服务使用ECS进行水平扩展,并通过lambda函数调用。这只是构成Prime Video应用程序的众多微服务之一。

问题是,他们将这种做法称为微服务到单体的转变,而这显然,只不过是微服务重构的一步。

5、微服务不应该是默认选择

这篇博客确实证实了一些开发者的怀疑,微服务相对于整体应用的优势经常被夸大;微服务的解决方案也并非在所有情况下都是最具成本效益的,因为它们总是会涉及使用多种昂贵的服务。

在Hacker News中,Ruby on Rails之父Hansson给出了这样的评价,“这篇文章理论上总结了一段时间以来席卷科技行业的微服务热潮,现在,所有这些理论的实践结果终于出现了。很明显在具体情况下,微服务是可能导致你系统复杂化的最大诱因。”

按照Hansson的说法,“在一个单一的、一致的团队和应用程序中,使用网络调用和微服务划分代替方法调用和模块分离,在几乎所有情况下都是非常疯狂且没有意义的,而无服务器会让情况变得更糟。”

《构建微服务》一书的作者微服务大师Sam Newman也在Twitter总结了以下的观点,“这篇文章更多的是在谈论功能定价模型与长期运行虚拟机的定价模型,这是完全合乎逻辑的架构驱动因素。虽然这个案例所提供的经验并没有太广泛的适用范围,但当情况发生时,改变想法的确是非常明智的。”

总而言之,即使是作为单个进程或整体部署的应用程序,在设计上也是可以进行模块化的,不同的团队在每个模块工作。实现了这一点,许多组织使用模块化整体架构的效果将比微服务更好。微服务不应当成为组织的默认选择,而应当是最后手段。

6、写在最后

归根结底,无论是微服务还是单体架构,都有着自身的优势与缺陷。但在过去几年中,太多的开发者被微服务的好处所说服并轻易对其进行了采用。这也导致了许多系统体量或是团队成员不足的组织的失败。换句话来说,当你没有明确看到当前系统的瓶颈时,先做所有简单的事情。

Prime Video的这篇博客对于许多支持分布式微服务的云巨头而言并不一定是一个坏消息。虽然在一方面,它违背了云巨头所倾向的最佳实践;但在另一方面,它提供了一条令人耳目一新的道路,以及一个非常成功的迁移案例。与许多我们所熟知的促销方式不同,这个案例可能对这些云巨头的客户而言将更有意义。

https://devclass.com/2023/05/05/reduce-costs-by-90-by-moving-from-microservices-to-monolith-amazon-internal-case-study-raises-eyebrows/

https://adrianco.medium.com/so-many-bad-takes-what-is-there-to-learn-from-the-prime-video-microservices-to-monolith-story-4bd0970423d4

https://www.primevideotech.com/video-streaming/scaling-up-the-prime-video-audio-video-monitoring-service-and-reducing-costs-by-90