学习如何应对微服务

Avatar of Eduardo Bouças
Eduardo Bouças

DigitalOcean 为您旅程的每个阶段提供云产品。立即开始使用 200 美元的免费额度!

我清楚地记得我第一次接触内容管理系统的情景:那是 2002 年,我使用了一个名为 PHP-Nuke 的平台。它提供了一个控制面板,网站管理员可以通过它发布新内容,这些内容会立即提供给读者,而无需创建/编辑 HTML 文件并通过 FTP 上传(当时这是我唯一知道的现实)。

一旦我转向了 CMS,我就没有回头。CMS 很快成为我作为 Web 开发人员工具包的一部分,我并没有真正停下来思考它们是如何工作的。我花了大量时间学习 Web 栈的各个组件;爱上并抛弃不同的语言、范式、框架和工具。我花了很长时间才停下来思考任何系统中最重要的部分:它如何管理和存储内容。

我开始着手探索更多关于 CMS 内部工作原理的信息:它如何真正工作以及当我们要求它处理用户、文章或分类法等事物时它实际上做了什么。

我意识到像 WordPress 或 Drupal 这样的平台的演变方式有一些奇怪的地方,那就是它们逐渐发展成为不仅仅是内容编辑工具,逐渐成为整个系统的支柱。这些平台为数百万个网站提供动力,控制着从数据库及其结构到业务逻辑,一直到前端模板的一切。

这在我看来对单个工具来说是巨大的权力和责任。我想知道这是否会成为一个问题。

环顾四周并展望未来

我们生活在一个多渠道和多设备的世界。至关重要的是,不同类型的系统(如第三方网站或原生应用程序)能够与您的数据交互。当前的 CMS 平台是否为此做好了准备?

例如,WordPress 在 PHP 和 MySQL 数据库上运行。这意味着每个需要与其通信的其他系统都需要运行 PHP 吗?如果其他系统想要插入新数据,它们是否需要能够连接到 MySQL 数据库?

在理想情况下,系统将能够使用其他系统可以理解的语言进行通信,而不管其编写的技术是什么。

如果您的内容管理需求发生变化会发生什么?编辑工作流程在许多组织中发挥着至关重要的作用,并且随着它们的演变和发展(或缩减!),它们的流程自然也需要发生变化。一些 CMS 可以适应以满足新的需求,但许多 CMS 却做不到。

如果您的 CMS 无法适应不断变化的需求,您可能会发现自己正在寻找新的系统。这会引发更多问题

  • 现有数据结构会发生什么变化?它是否足够灵活以插入到另一个平台?
  • 您是否与现有的技术栈绑定?
  • 将您的前端模板适配到新的 CMS 需要多少重构?

同样重要的是要考虑更极端的情况:如果没有网站会怎样?淡化 Web 存在的作用而转而支持原生应用程序是一种相当常见的现象。事实上,许多项目可能根本不涉及网站。传统的 Web CMS 是否仍然可以运行?

从我的角度来看,我想为编辑人员提供一个单一的平台,他们可以使用该平台发布内容,而不管最终将使用该内容的系统是什么。请记住,对于编辑人员来说,CMS 是他们唯一的窗口;他们花费时间使用编辑界面。随着时间的推移,更改他们的界面以支持不同的设备,或者更常见的是,强迫他们在多个地方创建和发布内容以针对这些设备,会严重影响生产力。

无头 CMS 和 COPE

一个典型的 CMS 是一个单体应用程序,在后台至少有四个组件

  1. 一个数据层,所有内容都存储在其中;
  2. 一个基于 Web 的界面,编辑人员可以在其中创建和编辑内容,以及管理分类法和多媒体资产(CRUD UI);
  3. 一个界面,网站管理员可以在其中以模板的形式创建和设计页面;
  4. 一个系统,它将来自数据库的内容应用于模板,生成要由最终用户使用的输出(对于网站,这将是 HTML)。

无头 CMS”的概念旨在解决这些组件之间的紧密耦合,消除上面突出显示的问题。这个想法很简单:将 1 和 2 与 3 和 4 分开,添加一个 API 层,该层接收和传递到数据库的数据,并使用通用语言(通常是 JSON)与外部世界通信。

图 1 - 单体 CMS 和无头 CMS 之间的比较

以这种方式工作,前端与提供数据的完全解耦,这意味着它不再受 CMS 采用的技术栈的限制 - 您可以在 Node.js 服务器上从运行 PHP 的无头 Drupal 中提取数据,甚至可以通过客户端 JavaScript 应用程序从 API 获取数据的静态 HTML 页面。

因为几乎任何人都可以理解 JSON,这还为其他系统使用数据创造了可能性,而无需强迫编辑人员在不同的平台上多次发布它。这个关键原则就是 COPE(创建一次,发布到任何地方)的基础,并且是向多媒体、多设备受众传递内容的强大方法。

当一家出版公司要求我使他们的 WordPress 安装能够向运行在不同技术栈上的多个前端系统(以及原生移动应用程序和广告单元)传递内容时,我采用了这种方法。

我在 WP REST API 之上创建了一个自定义 API 层,并在您可以找到 此处 的文章中记录了这段旅程。您现在正在阅读的内容是对此的后续:我继续追求真正解耦、灵活和可扩展的 COPE 系统。

进入微服务

无头 CMS 方法解决了我的大多数问题,但并非全部。即使数据现在与前端分离,数据库和 CMS 仍然紧密耦合在一起:如果我想更改 CMS,这仍然是一个问题,因为,如图表所示,进出数据库的所有内容仍然都通过它。(即使是与外部世界通信的全新的 API。)

此设置还会引发有关可扩展性的问题:随着 CMS 和 API 粘合在一起,系统有多容易扩展?例如,访问这两个组件的流量性质将大不相同,因此将它们置于不同的负载均衡器下可能更有意义。

为了解决这个问题,我想将 CMS 与 API 分离,并将其都作为自包含且可部署的服务运行。我开始与 DADI 的人员合作,使用他们的开源内容和数据管理平台,该平台是专门为支持微服务和 COPE 原则而构建的。他们的堆栈是一套模块化、可互换和可部署的服务,构建在 Node.js 上,具有以下组件

API

一个高性能的 RESTful API。内容存储为文档并分组到集合中。每个集合都使用 JSON 模式文件定义,其中定义了字段、验证规则和其他数据属性。

通过在特定 REST 端点上查询集合来存储和检索文档。除此之外,API 还公开了用于编辑任何配置文件的端点,例如集合模式,这意味着您还可以使用 REST 创建或编辑集合。

为了提供最大的灵活性,它还提供了自定义端点,这些端点可以使用自定义逻辑响应任何 REST 动词(并利用数据模型查询数据库),以及在请求生命周期的关键时刻触发自定义例程的钩子。

为了使 API 与其他系统的集成更加容易,有一套库,如 Passport,用于抽象身份验证层(可用于 Node.js、PHP 和 React Native),或 API 包装器,一个用于执行 CRUD 操作的高级工具包。

Web

一个无模式模板层,可以作为独立平台运行,也可以与 DADI API 作为完整堆栈 Web 应用程序一起运行。目前附带 Dust.js 作为其模板引擎(正在开发对更多引擎的支持),允许在服务器和客户端上呈现模板。

连接到 DADI API 实例时,DADI Web 可以利用数据源访问集合,并自动将文档提供给模板。与 DADI API 中的钩子类似,它以事件的形式提供了最大的灵活性,事件是可附加到页面并在渲染时执行的功能模块。

发布

功能齐全的编辑和内容管理界面,旨在优化编辑工作流程。

它以灵活性为核心构建,具有高级布局构建器,可以创建类似文章的文档,并能够在一个结构中混合和匹配不同的元素(如段落、图像或媒体嵌入),同时仍然将它们单独存储为不同的字段。

这使得轻松生成文章的不同版本变得容易,而无需抓取 Markdown 或 HTML:例如,您可以获取仅包含图像及其标题、摘录和标题的文章版本,或者前三段。

它内置了协作和完整的修订历史记录。

CDN

一个即时资产操作和交付层,设计为现代内容分发解决方案。

它完全支持缓存、标题控制、图像操作、图像压缩和图像格式转换。从原始图像,您可以即时请求多个变体,例如不同大小和分辨率的裁剪(想想响应式图像)甚至模糊版本。

CDN 包含一个内容感知裁剪工具,该工具能够分析图像内容以自动找到特定尺寸的良好裁剪,这对于图像艺术指导来说是一个改变游戏规则的功能。

下一个版本将引入路由的概念,这是一组规则,允许您根据用户的设备、语言、位置或连接类型等条件提供资产的不同变体。

图 2 — DADI 堆栈可能实现的示意图

与现有的无头 CMS 解决方案相比,这些解决方案实际上只是经过调整以提供 API 优先方法作为事后想法的单体应用程序,DADI 平台实际上是从设计之初就采用了 COPE 架构,并且使用微服务分离关注点是其核心。

一个真实的案例

我的团队刚刚帮助一家数字出版平台初创公司将其产品上线。交付成果包括两个原生移动应用程序(Android 和 iOS)、一个响应式网站和一个 CMS,所有这些都在非常具有挑战性的时间范围内完成(想想几天和几周,而不是几周和几个月)。

由于 DADI 堆栈的所有组件彼此独立,因此我们可以并行构建大部分交付成果。第一个要设计的组件是 API 层,因为它负责将内容提供给所有面向用户的应用程序,以及多个联合平台和用于所有营销和客户沟通的第三方电子邮件交付平台。

通过将业务逻辑直接转换为数据结构和验证模式,我们建立了数据表示的格式,并且 API 在流程早期就已准备就绪,不同的团队可以同时处理其交付成果,而不会影响其他团队。

我们有一个团队负责原生移动应用程序,另一个团队负责响应式网站(使用 DADI Web),一个工程师部署和自定义 DADI Publish 的安装,另一个负责使用 DADI CDN 处理资产操作和交付。

这种关注点分离使人们能够专注于自己的专业领域。前端工程师可以在使用 API 中获取的数据完成 Web 层后,而无需查看其实现。

原生应用程序的功能之一是基本的内容管理界面,编辑人员可以在其中轻松创建新的文章,这意味着应用程序本身正在发挥传统 CMS 中的关键作用。当然,由于一切都是模块化的,所以这绝对没问题。

使用微服务构建的美妙之处在于它适用于任何规模的项目:一个小型项目,其中同一实例运行 API、Web 层和编辑界面;一个大型项目,其中数十个 API 为由一个或多个 Publish 实例控制的多个 Web 前端提供数据;以及介于两者之间的任何内容。使用任何可能的组件组合,系统可以随着时间的推移根据需求的变化逐渐从一个极端扩展到另一个极端。

当将 Amazon AWS 等云计算服务加入其中时,这变得更加有趣。如果系统出现突然的流量激增,它可以快速扩展到特定层中的数十个实例,而不是一个实例,并在情况平静下来时缩减回正常状态。

总结

自从 2002 年和 PHP-Nuke 以来,我们已经走了很长一段路!我们作为用户和编辑的期望呈指数级增长,设备环境也发生了翻天覆地的变化。

很难预测下一个挑战是什么,当然,没有任何系统是完全面向未来的。但我相信,微服务带来的关注点清晰分离使您尽可能接近这一无法实现的目标。

对我来说,最令人兴奋的事情是,我向您展示的平台可供任何人使用和体验。如果您真的有兴趣,您甚至可以为这些项目做出贡献

如果您有任何疑问或需要帮助设置 DADI,请随时在 Twitter 上联系我