平台工程的未来:平台即运行时
本文介绍了 Wix 公司在打造面向开发人员的统一开发者平台的过程中学到的经验,介绍了真正有价值的开发平台应该覆盖的范围和功能,对于希望打造自己开发平台的团队有很好的借鉴意义。原文:Platform as a Runtime - the Next Step in Platform Engineering
简介
许多公司转向平台工程来帮助扩展开发团队,并提升工程效率,优化开发体验。然而,平台工程通常止步于 CI/CD 流水线。随着系统变得更大、更复杂,我们需要将平台工程的理念提升到更高的水平 —— 到代码水平 —— 通过创建平台和抽象来减少认知负荷,帮助简化并加速软件开发,同时构建更易于维护和升级的平台。这将有助于减少对全公司各个团队都有影响的任务,比如修复臭名昭著的 Log4J 安全漏洞。既然如此,是否可以通过减少每个微服务的开销来降低云成本,从“平台”转移到“作为运行时的平台”。
复杂软件系统对开发人员和组织的影响
庞大而复杂的系统会阻碍公司创新和快速适应的能力。这些系统通常要求开发人员处理大量信息和问题,导致认知过载。作为工程经理,我亲眼目睹过这一切。新特性的开发,无论其大小,都可能因为需要处理大量横切关注点(如网络合约、规则以及与核心业务需求并存的各种非功能需求)而大大放缓。对于 Wix 来说尤其如此,Wix 是一个向第三方开发人员公开许多 API 的开放平台,因此所有服务都需要以相同的方式工作,我们有许多关于如何构建服务以及处理规模化问题以及构建生态系统的最佳实践和指导方针。
例如,软件平台可能要求每个数据库变更操作都需要发送域事件。开发人员需要记住定义域事件消息并实现在每个数据库操作上,这一事实增加了认知负荷、时间和功能复杂度。在每个系统中都有许多额外需求,例如系统可能需要支持多种语言和货币,确保符合 GDPR 法规,处理“删除”通知,实现最佳实践(如乐观锁或在每个数据库模式中除了最新更新日期之外还有版本字段),与其他子系统(如 IAM 或生态系统中的其他组件)集成。不断增长的考虑因素和“最佳实践”列表,会不断增加系统复杂性,显著延长发布周期。
为什么软件变得复杂
软件系统开始时通常很小,但随着发展演进,逐渐变成了复杂系统,具有复杂的依赖关系,使我们很难理解某个部分的变化如何影响另一个部分。
软件系统正变得越来越大,并且分布在多个服务器和云组件上。管理和维护这些分布式系统增加了另一层复杂性。每个组件和特性都有自己的最佳实践,需要专门的知识。例如,要发送域事件,需要了解如何使用 Kafka,学习它的 API,它的交付保证(至少一次)以及使用 Kafka 的最佳实践。
这同样适用于 MySQL 或 MongoDB 这样的数据库,以及 Elastic search 这样的搜索引擎,甚至集成的其他内部服务,比如特性标签系统。基本上,你需要了解并学习如何以最好的方式使用每个组件。
另一个导致复杂性的因素是缺乏跨团队和开发人员的标准方法。例如,某个开发人员定义了一个主键为 UUID 的数据库模式,而另一个开发人员定义的主键是 Long。某个开发人员可能实现了“删除”和“获取我的数据”的 GDPR 功能,而另一个迫于业务压力而快速发布功能的开发人员只开发了“获取我的数据”,而没有“删除”功能。甚至同一个功能可以有不同的实现,例如,某个开发人员将“GDPR 删除”实现为硬删除,另一个实现为“软删除”,而第三个实现为数据匿名,并没有实际删除记录。虽然这些都可能是有效的解决方案,但当有人(即法律团队)问你如何实现 GDPR 删除时,答案不应该是“视情况而定”。系统应该以可预测和一致的方式运行。
几乎不可能确保所有开发人员 100% 遵守系统的所有非功能性需求,甚至像输入验证这样简单的事情也可能因开发人员而异。例如,有些不允许字符串字段为空,而另一些允许为空,导致整个系统实现的不一致。
通常,让所有开发人员在最佳实践和非功能性需求上保持一致的第一步是编写文档、定义检查规则,以及培训。然而,在复杂的世界里,不可能建立完美的系统。当开发人员需要实现新功能时,他们需要做出权衡。
很多情况下,我们会考虑三个方面的权衡:
代码 —— 当选择如何构建系统时,例如选择单体还是微服务,我们面临几个可能影响决定的问题。是否容易理解现有代码和领域?是否可以破坏某个 API,以及它对系统的影响是什么?是否容易重构和测试代码?如何扩展工程组织以便多个团队在编写特性时可以不依赖或尽可能少依赖其他团队?
部署 —— 在这个方面,我们对发布生命周期进行权衡。例如,多个团队是否可以随时将其代码的新版本发布到生产环境中?部署过程是否简单、快速?每次部署的风险是什么(部署的代码越多,出现 bug 的可能性就越大)?另一件需要考虑的事情是保持向后兼容性和破坏 API。例如,在单体应用中,很容易重构并破坏(内部)API,因为每个人都可以控制整个代码库,而在微服务环境中,由于其分布式特性,只有意外事件才会破坏 API。
运行 —— 在这个方面,我们考虑系统的运维。性能需求是什么?扩展系统的各个部分是否容易?当我们在生产环境中运行时,是否容易理解(监控)系统?万一发生事故,能否快速找到系统故障部分的所有者?
虽然文档定义了如何开发软件以及推荐的最佳实践的必要步骤,但实际上,开发人员有很多自由可以选择实现功能的内容和方式。不同团队可以拥有不同的内部库,这些库以不同的方式实现部分指导方针和系统契约。
这些不同的实现在整个系统上造成了不断增加的技术债务,因为跨系统需求中的每个变更都需要多个团队进行更改,甚至需要在做相同事情的不同实现中修复同样的错误。比如不久前的 Log4J 漏洞就需要每个团队都进行修复。确保代码库 100% 得到修复是项艰巨的任务。
标准化的必要性
复杂环境更需要标准化编码实践。
虽然定义标准和整合技术栈至关重要,但仅仅记录下来还是不够。正如前面提到的,过多的文档会使开发人员信息过载。
解决之道在于代码化,将标准、指导方针和最佳实践转固化为开发平台,通过平台自动处理系统的大部分横切关注点,使开发人员更容易编写符合标准的代码,从而为快速开发产品功能创造黄金通道。
例如,PII 字段加密,平台应该自动处理字段的加解密,而不需要开发人员学习、理解甚至使用加密库。比方说,只要将字段注释为 @PII
,平台就会在数据库写入和读取时自动加解密该字段,因此开发人员甚至不需要在代码中考虑。
由于开发这样一个健壮的平台成本非常高,我们试图尽可能限制软件栈的规模。不受限的偏离标准平台会增加系统的复杂性和维护负担,因此应该仔细评估任何偏离,并考虑引入该偏离的额外复杂性。
对标准化的需求是为了减轻规模化的挑战。微服务是尝试处理规模化问题的另一种解决方案,但随着微服务数量的增长,将面对大规模微服务环境的复杂性问题。
在分布式系统中,由于网络问题,请求可能会失败。而由于请求通过网络通信在多个服务之间流动,而不是在单体中调用进程内方法,因此性能也会降低。监控系统变得更加困难,因为调用分布在多个服务之间。更大的问题是安全性,因为每添加一个微服务,就会增加攻击面。不要忘记人的因素:跨多个团队和服务维护标准化、高质量以及通信协议将变得更加困难。
这些都是明显缺点,但大型系统遇到的隐藏问题是成本和可维护性,下面来解释一下:
当编写微服务时,通常会使用某种框架,如 Spring,同时有需要的所有内部库和依赖项,例如构建并打包到微服务中的日志库和 JDBC 驱动程序等。这意味着在微服务中运行的超过 90% 的代码实际上是打包和部署的框架和库。在每个微服务中实际编写的业务逻辑最多只占代码的不到 10%(取决于微服务的规模)。许多情况下,业务逻辑甚至还不到微服务中打包代码的 1%。
所有这些代码都在生产环境中被复制和部署了成百上千次,每增加一个新的微服务都会增加占用空间,反过来又增加了云成本,并使不同框架和库版本的对齐变得更加困难。
在 Wix 运维超过 4000 个微服务集群,给我们带来了很多痛苦,所以我们试图通过构建平台即运行时(PaaR,Platform as a Runtime)来缓解这些问题。
为了分析问题域,我们研究了开发人员如何编写代码,以及如何考虑三个方面选择技术栈:代码、部署和运行时。我们将解决方案分为两个部分:平台和运行时。
平台:自动化的开发者体验
平台通过内置最佳实践、契约、规则,以及其他一些重要的东西,集成到生产环境的代码中间件组件中,专注于开发体验。可以把它想象成一个高度定制的框架,满足公司的特定需求。平台处理非功能性需求,减少样板代码,并最小化认知负荷。当开发人员在平台内工作时,所有事情都可以按预期工作。
我们内部称这个项目为“Nile”,重点是简化软件开发,目标是专注于开发体验,为开发人员带来最大价值。
这种方法超越了传统框架和平台工程,我们将平台工程从 CI/CD 级别带到代码级别。大多数公司提供框架给开发人员使用,但没有创建一个将框架与组织的操作实践无缝集成的平台。
例如,考虑遵守 GDPR 规范,为了完成 GDPR 数据删除请求,通常会订阅某个 Kafka 主题并监听“删除数据”请求。某个基本框架也许可以帮助我们轻松订阅主题,但开发人员仍然需要编写消息处理和删除逻辑。然而,一个健壮的平台将自动订阅 GDPR 主题,处理消息,并从数据库中发起数据删除操作。所有这些都不需要开发人员额外干预,开发人员唯一需要做的就是注释 PII 字段,平台将自动完成其余工作。
运行时:优化服务开销和部署
PaaR 的运行时部分致力于优化服务开销和部署策略。运行时保存平台代码并管理所有网络通信(输入和输出),而不是将整个平台框架与代码工件捆绑在一起。这消除了将平台与每个微服务打包的需要,使平台的独立发布周期与产品工件分离。每个部署的工件都简单的连接到运行时,从而减少服务占用,并将其视为运行时依赖项,而不是构建时依赖项。
通过减少工件大小,PaaR 允许在节点内实现更大密度的部署。客户机(即产品微服务)的占用空间大大减少,因为不需要与所有框架和公共库捆绑在一起。单个运行时主机可以有效的为多个客户服务提供服务,从而创建一个虚拟的单体。
为了支持更广泛的编程语言,我们启动了一个名为“SingleRuntime”的“平台即运行时”计划,通过本地网络(localhost)使用 gRPC 协议与客户服务进行通信。这种方法将使我们能够在保持统一平台的同时使用多种语言进行开发。
虽然 PaaR 仍在开发中,但已经和 Nile 一起取得了重大成功。平台为开发者带来了很多价值,我们设法将内部开发者的开发速度提高了 50%-80%。开发人员体验得到了改善,他们现在可以专注于构建产品业务逻辑,而不用花费大量时间编写样板代码以及实现非功能性需求,从而减少了编写和测试的代码量,并能以更快的速度发布产品。
该平台的影响是如此巨大,以至于我们决定明年在公司层面将所有遗留服务(有数百个遗留服务)重写为 Nile。
采用单一标准平台的另一个被低估的好处是提高了产品质量,它做了很多繁重的工作,产品开发人员可以从重复实现非功能性需求中解脱出来,因为这些需求现在由平台提供,并由平台团队以最有效的方式根据最佳实践实现。此外,添加到平台的任何新功能都会自动在平台内构建的所有服务上可用并激活,从而节省了跨团队的工作。
数据本地化就是一个很好的例子。在我们迁移到 Nile 之前,只有几个服务支持数据本地化,但当我们将数据本地化支持添加到 Nile 平台之后,数百个以前不支持数据本地化的服务在一天之内都支持了这一功能,而这一切都不涉及任何产品开发人员。一旦他们使用新的平台进行编译,就免费获得了数据本地化支持。和没有统一平台的情况相比,这为公司节省了数百人周的时间。
应该构建自己的 PaaR 吗?
开发运行时平台(PaaR)解决方案是一项艰巨任务,最适合面临重大规模化挑战的组织。如果公司的微服务环境相对较小,在服务数量不足 100 的情况下,可选的、更经济有效的扩展解决方案可能更可取。可以从强制执行标准库开始,维护对第三方依赖项的严格控制,并构建规则来强制执行标准。我们在 Wix 构建过一个“普遍可用”(GA,generally available)强制检查,该检查强制每个人至少每两周使用最新的库和框架将其工件部署到生产环境中。
一旦扩展到数千个微服务,就可以开始构建平台。
对于准备开始 PaaR 之旅的组织,我的建议是优先构建平台。通过将平台工程提升到更高的抽象层次 —— 不仅仅是基础设施,还有软件层本身 —— 专注于自动化、简化开发过程以及集成。
专注于业务逻辑对我们来说是有效的,因为平台团队的客户是产品开发人员。
构建平台涉及到对数万行代码的严格审查,我们的方法是用评估的每一行代码来挑战我们自己,问自己这个问题:“这行代码属于这里吗?”该平台的设计目标是将核心业务逻辑隔离在代码库中,并将其他所有内容编码到平台中,而不是产品服务本身。正如史蒂夫•乔布斯(Steve Jobs)曾经说过的那样:“编写速度最快、永远不会出错、不需要维护的代码是你永远不需要编写的代码。”听起来很天真,我们的 KPI 是代码行数,目标是尽可能减少产品开发人员必须编写的与业务逻辑无关的代码行数。
我们学到的重要教训是,平台团队需要保持正确的心态,必须以价值为导向。虽然这可以是一个单独的主题,不过我还是想提一下:平台团队最关键的 KPI 是“开发者采用率”。如果开发人员不使用你的平台,就意味着平台无法提供真正或足够的价值。这对团队来说至关重要,与产品开发人员的合作对平台的采用非常有帮助,产品开发人员可以参与定义平台功能、能力和设置,从而真正解决实际问题。
最后我想分享是,实现这些目标的道路并不容易。除了技术上的挑战,还有人为因素。开发人员可能会对抽象和不可见的功能感到担忧。为了赢得开发者的心,关于平台内部运作的持续沟通和持续教育至关重要。这种透明性可以揭开平台的神秘面纱,并使开发人员能够有效进行调试并做出贡献。
你好,我是俞凡,在 Motorola 做过研发,现在在 Mavenir 做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI 等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!
版权声明: 本文为 InfoQ 作者【俞凡】的原创文章。
原文链接:【http://xie.infoq.cn/article/c5a98e7bd874e9bda21f8d5ba】。
本文遵守【CC-BY 4.0】协议,转载请保留原文出处及本版权声明。
评论