2500人的研发团队如何借助平台工程服务近2亿用户?

Wix 是一家成立于2006年的网站搭建平台,在全球拥有来自190个国家和地区的2亿个用户。Wix 整体团队规模在5000人左右,其中一半是研发人员。因此,早在十多年前 Wix 开始实践平台工程,彼时“平台工程”这个概念尚未被提出。
 
本文由 Wix 的工程副总裁撰写,他将介绍过去几年 Wix 的平台工程实践以及一些新的平台项目和对未来的展望。
 

01 对软件开发速度的需求

成功的软件模式会快速交付出高质量的代码。但在规模不断扩大时,会面临许多挑战。随着公司不断发展壮大,由于持续增加的依赖项、旧代码以及复杂性,会导致软件开发流程变慢。
 
自从有了计算机科学和工程之后,产生了多种方法来组织软件开发,并找到方法来达成更快的交付速度和更好的交付质量,当前最为流行的方法是持续交付、DevOps 和 Serverless。
 
2500人的研发团队如何借助平台工程服务近2亿用户?_第1张图片
 
由于方法不断迭代,我们使用的工具也在不断变化。工具的更迭是为了帮助企业更快交付软件,科技初创公司数量的增长对于工具迭代也有积极影响。随着这种增长,我们看到了云主机/云计算供应商的出现,使人们能够快速访问庞大的数据中心的服务器,从而减少运维开销和成本。
 
接着是微服务的理念出现,它能使公司更快地扩大规模,更“容易”地维护软件。现在,我们还有 Serverless,使得开销降低,甚至无需维护生产服务器,从而使运维开销更少。
 

02 微服务如何影响开发速度

如果你只是刚开始进行软件开发或者你正在构建单个服务(单体架构),那么一切都比较简单。你可以使用任意框架并且利用你所掌握的工具。
 
但当软件开始扩大规模时,一切将会变得越来越复杂,因为你不止要构建一个服务。你建立了一个与其他服务和系统集成的东西,而这个东西现在需要通过 RPC/REST、数据库、消息中间件等连接到其他服务。现在你有了需要运维、测试和维护的依赖项,进而需要围绕所有这些建立某种框架。
 
然而,目前只有少数几个微服务,这仍然是一个相当简单的架构。随着软件不断发展,会增加越来越多的微服务,你就会得到类似下面的图片。这是 Wix 的微服务地图,每个矩形都是一个微服务集群,水平线和垂直线是它们之间的通信。
 2500人的研发团队如何借助平台工程服务近2亿用户?_第2张图片
 
正如你所见,许多微服务也意味着许多团队在为此工作。由于所有微服务都需要和谐共处,因此需要考虑它们之间的共同因素,比如同样的“语言”、相同的协议,如何处理 cookies 和安全问题,如何处理 PRC 调用、日志等。
 
下图列出了可能需要考虑的首要因素:
 
2500人的研发团队如何借助平台工程服务近2亿用户?_第3张图片
 
那么我们应该怎么做呢?我们通过一个共同的框架、语言来创建了一套标准,否则每个开发者都需要照顾所有这些重复出现的问题。
 
更糟糕的是,在 DevOps 文化中,对开发人员的期待包括熟练地维护生产环境、负责机器配置、了解数据库和 Kafka 集群、防火墙、负载均衡,确保弹性伸缩被正确配置、构建监控面板、了解分布式系统和跨区域复制数据等。
 

03 微服务架构的冰山一角

让我们来看看示例服务以及所构建的层级。最底部是提供计算能力的虚拟机,服务在容器内运行,往上是微服务/应用框架层,如 JVM 生态中的 Spring、NodeJS 的 Express,或者其他框架。然后,在这之上构建可信环境框架,这层主要是为了让所有底层服务都能以相同的方式进行通信。通过相同的协议,使用同样的 HTTP header,用相同的加密/解密算法,等等。这样,它们就可以被网络中的所有其他服务所使用和信任。
 
2500人的研发团队如何借助平台工程服务近2亿用户?_第4张图片
 
在构建了所有层之后,接下来是软件开发者需要进行的实际工作了。在这个金字塔的最顶端指你所有构建的服务带来的商业价值,即企业向客户销售的部分。
 
对于工程师来说,这只是冰山一角。在我们能够处理顶部的业务逻辑代码之前,我们需要处理整个底部的部分。但实际情况中并不止于此,除了需要开发产品的实际功能外,开发人员还需要考虑到合规、商业以及法律问题,例如 GDPR 合规性。这不是企业的卖点,但是需要开发人员在每个新构建的服务中考虑这些因素。
 

04 Platform as a Runtime (PaaR)

通常情况下,当构建一个微服务时,使用内部的框架和库,这些框架和库将与你的代码一起编译,为你提供大部分通用功能,如 gPRC、Kafka 客户端、连接器(connector)、A/B测试等。然而,通过这种方法,最终会得到一个分布式的通用框架,需要不定期更新所有微服务以确保所有服务的版本之间是互相兼容的。
 

对于这类依赖项的开销,我们能做些什么呢?

一个解决方案是将框架的依赖项从构建时改为运行时的依赖项。但在 Wix 我们更进一步。在建立一个内部框架时,除了我们之前提到的通信协议和合同之外,还会关注其他因素,比如共同的业务流、法律因素(GDPR、PII等)、租户模式、权限以及身份管理等。
 
因此,我们把所有这些业务关注点和流程作为运行时的依赖项加入,最终形成了平台即运行时(PaaR,Platform as a Runtime)。这意味着现在在 PaaR 中运行的每个微服务都会自动为研发人员处理相关问题,而不需要单独在每个服务中进行开发。例如,对于 GDPR,所有服务都会自动处理 GDPR 请求,以获得相关的合规数据,从而节省为每个服务都进行开发的宝贵时间。
 
我们是如何处理的呢?
 
我们从 Serverless 平台开始入手,其核心是 NodeJS 支持整个应用框架。为什么选择了 Node.js?因为它轻量,并且支持动态代码加载,容易上手。
 
Step 1:我们将整个框架与 GRPC / REST / Kafka 的集成层(包括发现服务)一起编码到 Node.js 服务器中,并使其成为“运行时服务器”。所以现在我们有一组相同的“运行时”服务器,它们具有相同的功能(框架)。
 
Step 2:我们又增加了一层数据服务,让开发人员便捷地连接数据库(运行时处理所有连接字符串、连接池、JDBC等)。我们最终得到的是一个“智能”容器,它可以处理入口流量并将所有常见的问题嵌入其中,但不包含太多的业务逻辑。
 
现在,开发人员可以使用运行时依赖项(Serverless)来构建业务逻辑,而无需将框架与他们的代码一起编译和打包,因为在你将代码部署到运行流程中时,会为你提供框架。
 
2500人的研发团队如何借助平台工程服务近2亿用户?_第5张图片
 
当开发人员准备好进行部署时,在 Serverless 生态系统中则无需担心 Node.js 或容器的问题,只需部署 TypeScript 文件或 Bundle 即可,该文件就会被动态地加载到平台运行时中去。
 
既然我们在运行时中已经有服务集成层,那么当你需要调用另一个服务时就不需要进行查询或发现,你只需要简单地声明你所需要的服务,平台就会为你提供相应的客户端以连接到你的依赖服务。
 
由于所有集成都通过“运行时”完成,因此还为你节省了集成测试,并且可以在代码中使用客户端库。
 2500人的研发团队如何借助平台工程服务近2亿用户?_第6张图片 
主要优势是你只需要部署你所需要的代码,无需将库和 node.js 运行时绑定,这使得部署的代码非常小,因为它只包含你编写的实际业务逻辑(通常小于 100kb )。
 

将项目结构与可部署的拓扑结构分开

到目前为止,我所描述的类似于标准 Lambda 函数(但如果是 Lambda 函数,你需要将框架和可部署项绑定)。但是,当你想添加另一个功能时会发生什么呢?如果是 Lambda,你需要对一个实例进行完整的设置或者将两者打包在一起,但由于我们是在一个可信的环境中运行的,因此可以在同一个进程中运行多个函数。基本上,我们可以开发独立的微服务甚至是功能,但需要将所有功能作为一个整体部署到同一进程中运行。然而,我们也可以将功能部署到不同的 PaaR 主机上。
 
或者反其道而行之,把软件开发成一个微服务,甚至是一个单体,但把部分服务部署到不同的 PaaR 主机上。
 
一个典型的例子是当你有两个端点的服务时,一个是需要响应用户请求的 RPC 端点,另一个是监听 Kafka 主题的端点,我们可以在同一个项目中开发这两个功能,以便开发人员将这两个端点放在一起考虑,就好像它们是同一个“逻辑”服务的一部分,但将 RPC 功能部署到一个主机,将 Kafka 监听器部署到另一个主机。
 
这将导致启用不同的扩展策略。我们可以对“面向客户”的 RPC 功能和 Kafka 服务进行不同的弹性伸缩,而开发人员无需处理将这些服务分离为两个不同服务的认知负担,以及随之而来的所有框架开销。
 
在Wix,我们搭建了一个系统,让部署一个功能变得非常便捷。开发人员将他们开发好的功能推送到 GitHub 仓库后,只需1分钟就可以将代码部署到生产中并运行,因为代码很小,只有业务逻辑,没有模板和捆绑的代码库。
 

05 平台工程思维方式

我们这样做有什么收获?

  • 集成变得非常容易:开发人员可以通过声明他想调用的功能/微服务即可自动获得相应的客户端库

  • 测试更少的代码:无需对黏合代码(glue code)进行集成测试

  • 开发人员可以编写和部署非常小的功能,只需关注他们所编写的业务逻辑的本质

  • 部署很快:代码很小并且无需打包框架/代码库

  • 0 模板(boilerplate):所有集成都已经预配置并仅通过声明提供给开发者使用
     

06 对未来的展望

接下来,我们如何利用目前所拥有的东西并在此基础上进行建设?假设我们想让不同的团队负责管理它们自己的运行时。我们可以通过克隆我上文提到的设置来做到这一点。例如,电子商务和博客团队可以各自拥有自己的运行时集群。这样一来,如果有需要,不同团队的代码就不会被推送到同一个运行时。同时,你仍然能够在运行时之间调用函数。
 
在这种情况下,我们希望能够根据运行时来优化某个功能的亲和力(affinity)。假设我们有2个运行时,每个运行时包含几个功能:
 
2500人的研发团队如何借助平台工程服务近2亿用户?_第7张图片
 
如上图所示,Function2 和 Function5 频繁互动。但由于它们被部署在不同的运行时中,网络调用比较慢。如果我们能让系统自动将 Function5 部署到第一个运行时,将 Function2 部署到第二个运行时,那么最后我们会得到这样的架构:
 
2500人的研发团队如何借助平台工程服务近2亿用户?_第8张图片
 
通过组织和优化运行时中的功能,我们可以拥有一个高度优化的运行时环境,微服务之间的网络调用最少。
 

07 未来已来,“单一运行时”

我们对另一个未来的发展感到兴奋的是扩展到其他编程语言。我认为,这需要一个范式的转变:不要建立一个多语言系统,不要为多个技术栈多次构建同样的框架,而是使用一个实际上支持任意语言的单一运行时。
 
我们通过将“冰山”一分为二,一方面将单个运行时框架、服务集成和数据服务层分开。我们称其为“主机(Host)”,集成层以主机+业务逻辑为“Guest”。我们的想法是能够只开发一次应用框架,而不是不断尝试在不同编程语言的框架之间实现功能的对等。这种方法的一个明显优势是仅在主机上运行框架更新,而不必为您支持的每种语言/开发栈复制框架/运行时,而且只需执行一次。
 
缺点是我们不会在进程中运行实际的业务逻辑,但主机和 Guest 在进程外(相同localhost)进行通信。我们还在用 GraalVM 进行实验,看看是否能在进程中与主机一起运行多个不同编程语言的 Guest,但现在我们有2个不同的进程,这使得我们的工作更轻松,并且系统可以正常工作。
 
2500人的研发团队如何借助平台工程服务近2亿用户?_第9张图片
 

08 当前进展

这种方法成功体现在我们的开发人员对它的喜爱程度上,其核心是平台工程的思维方式,我们把许多复杂的问题变得简单。Wix 的开发人员现在能够在几个小时内开发出以前需要几天甚至几周的东西。
 
从本质上讲,我们把平台工程从一个低级别的开发者门户变成了一个完整的 PaaR,同时也减轻了生产中低级别维护所产生的认知负担。
 

原文链接:https://www.aviransplace.com/post/platform-as-a-runtime-paar-beyond-platform-engineering
转载请联系:[email protected]

你可能感兴趣的:(运维开发)