在云社区和敏捷编程社区中,好像大家都在谈论微服务。REST 等架构原则正在风靡整个开发世界,微服务目前是最新一波的热潮。但是,微服务是什么?为什么 Java™ 开发人员会关心它们?
在本系列中,我将回答这些问题,并解释为什么您要将自己的应用程序迁移至微服务(第 1 部分)。我还将深入探讨数据重构(第 2 部分),并给出一个循序渐进的方法来帮助您迁移到微服务(第 3 部分)。
在 Martin Fowler 和 James Lewis 关于这个问题的经典文章 中,我们可以找到最简单的 微服务架构 定义:“一种架构方法,包括利用小型服务在各自的过程中构建系统,以及利用轻量级协议进行通信。” 要理解的一个关键概念是,每个微服务代表一个独特的业务功能。
Fowler 还将微服务称为 “正确完成的面向服务”。如 Fowler 和 Lewis 所述,而且其他许多人都已证明,企业计算的世界中,到处都是失败的大型 SOA 项目的范例。微服务可以 帮助扭转这一趋势,但我们必须明白在什么地方应用微服务,更重要的是,我们要了解可以发挥微服务最大作用的项目,而不是目前那些最巧妙的、最酷的项目。
尽管在硅谷的人有时愿意相信,但并非每一个应用程序都是一块绿地。现实情况是,企业有很多现有的 Java 代码,以及许多 Java 开发人员。扔掉所有的 Java 代码,用全新的运行时和编程语言重新开始,从经济角度来看,这根本就是不可行的。
更好的办法是,找出好的部分,并在正确的框架中重用这些部分。这就是为什么将现有的应用程序 重构 到微服务往往是最好、最稳妥的办法,可以在保持现有的系统运行的同时将它们迁移到一个更加可持续的模型中。
那么,我说的 重构 是什么意思?编程社区将重构定义为 “引入保持行为的代码转换”。这可以归结为保持外部 API 不变,而改变代码运算或打包的方式。因此,重构到微服务就意味着,将微服务添加到应用程序,而不必改变它所做的事情。您不会在应用程序中添加新功能,但您会改变它的打包方式,或许这就是这个 API 的表达方式。
重构到微服务并非适合所有应用程序,而且并不是总能获得成功。但是,当您不能把所有一切都扔掉的时候,重构是值得考虑的。三个基本的考虑事项是:
最好的起点是,重新检查您的 Java 应用程序打包结构,采用一些新的打包实践,然后再开始修改代码。在 21 世纪初,我们开始构建一些越来越大的 EAR 文件,以包含我们的逻辑应用程序。然后,我们将这些 EAR 文件部署到服务器场中的每个 WebSphere® Application Server 上。问题是,这种做法试图对应用程序的每段代码都使用相同的部署时间表和相同的物理服务器。任何改变都意味着要重新测试一切,这使得任何改变都变得过于昂贵,不在考虑范围之内。
但现在我们使用了 Docker 等容器和 PaaS,以及 WebSphere Liberty 等轻量级 Java 服务器,经济因素已经发生了改变。所以,现在您可以开始重新考虑打包。下面是您需要开始运用的三项原则:
您可以看到运用这三项原则的效果:
现在,您的部署策略已经细化到了独立 WAR 的层次,您可以开始寻找机会将 WAR 重构为更精细的水平。以下有三种情况,您可以在其中找到机会重构代码,以适应独立包装微服务的包装方法。
:如果您已拥有一些服务,它们可能是遵循某种功能方法(比如 Service Façade 模式)构建的。在这种情况下,以功能为基础的服务设计通常可以被重构为基于资产的服务设计。这是因为,在许多情况下,Service Façade 中的功能最初都被编写成在单个对象上的 CRUD(创建、检索、更新和删除)操作。如果是这种情况,可以简单地映射到一个 RESTful 接口:只需将 EJB 会话 bean 接口或 JAX-WS 接口重新实现为 JAX-WS 接口。为此,您可能需要将对象表示转换成 JSON,但这通常不是很困难的,尤其在您已经使用了 JAX-B 进行序列化时。
在不是一组简单的 CRUD 操作的情况下(比如,转账),那么,您可以应用一些不同的方法来构造 RESTful 服务(比如构建 /accounts/transfer 等简单的功能服务),实现 Command 的异体模式。
一旦构建并重新打包在上述三种情况下定义的小服务,您可能会希望将注意力转移到可能是采用微服务的最困难的问题:重构作为您的应用程序的构建基础的数据结构。我们将在本系列的第 2 部分更深入地探讨这个难题。但在最简单的情况下,也可以遵循一些规则:
:从查看您的代码使用的数据库表开始。如果您使用的表独立于其他所有表,或者通过关系联接的几个表进入一个 “孤岛”,那么您可以只将那些表从数据设计中拆分出来。完成这项工作后,您就可以考虑采用适当的服务选项。
例如,您想留在 SQL 中,或许可以考虑从重量级的企业级数据库(如 Oracle)迁移到一个较小的自包含数据库(比如 MySQL)?或者,可以考虑用 NoSQL 数据库来取代 SQL 数据库?该问题的答案取决于您对数据执行的实际查询类型。如果大多数的查询都是对 “主” 键的简单查询,那么一个 “键-值” 数据库或文档数据库就能很好地满足您的要求。另一方面,如果您确实有变化很大的复杂联接(例如,您的查询是不可预测的),那么,继续用 SQL 可能是您最好的选择。
现在您已经大致了解了重构到微服务的意义,以及在选择方法时要考虑哪些因素。好消息是,重构代码并不像想像中那么难,在很多情况下,它实际上是非常简单的。如果您仔细检查自己的代码,寻找这些(相对)简单的情况,您可能会发现,更复杂的代码段其实并不多见。
在这一系列的第 2 部分中,我们将更深入地探讨数据结构如何影响将微服务引入到应用程序中的方式的选择。