企业借助有效的应用程序重构微服务的3大步骤

企业借助有效的应用程序重构微服务的3大步骤

第 1 步: 重新打包应用程序

最好的起点是,重新检查您的 Java 应用程序打包结构,采用一些新的打包实践,然后再开始修改代码。在 21 世纪初,我们开始构建一些越来越大的 EAR 文件,以包含我们的逻辑应用程序。

问题是,这种做法试图对应用程序的每段代码都使用相同的部署时间表和相同的物理服务器。任何改变都意味着要重新测试一切,这使得任何改变都变得过于昂贵,不在考虑范围之内。

但现在我们使用了 Docker 等容器和 PaaS,以及 WebSphere Liberty 等轻量级 Java 服务器,经济因素已经发生了改变。所以,现在您可以开始重新考虑打包。

下面是您需要开始运用的三项原则:

1.拆分 EAR:不要将所有相关的 WAR 打包到一个 EAR 中,而是将它们拆分成独立的 WAR。这可能涉及到一些小的代码改动,或者更可能的是,如果您将应用程序的上下文根改成是分开的,将会涉及要修改静态的内容。

2.应用 “每服务容器 (Container per service)”:接下来,应用 “每服务容器” 模式,将每个 WAR 部署到它自己的 Liberty 服务器中,最好是在它自己的容器中(比如一个 Docker 容器或一个 Bluemix 即时运行时)。然后,您可以独立地扩展容器。

3.独立地构建、部署和管理 :一旦进行了拆分,您就可以通过自动化的 DevOps 管道(如 IBM DevOps Pipeline Service)独立地管理每个 WAR。这是获得持续交付的优势的一个步骤。

您可以看到运用这三项原则的效果:

第 2 步. 重构代码

现在,您的部署策略已经细化到了独立 WAR 的层次,您可以开始寻找机会将 WAR 重构为更精细的水平。以下有三种情况,您可以在其中找到机会重构代码,以适应独立包装微服务的包装方法。

第 1 种情况:现有的 REST 或 JMS 服务:这是迄今为止最简单的重构情况。您可能已经有一些服务可以兼容微服务架构,或者可以让它们变得兼容。首先从 WAR 中清理出所有 REST 或简单的 JMS 服务,然后将每个服务部署为它自己的 WAR。在这个层面上,配套 JAR 文件的副本是没问题的;主要仍然是包装问题。

第 2 种情况:现有的 SOAP 或 EJB 服务:如果您已拥有一些服务,它们可能是遵循某种功能方法(比如 Service Façade 模式)构建的。在这种情况下,以功能为基础的服务设计通常可以被重构为基于资产的服务设计。这是因为,在许多情况下,Service Façade 中的功能最初都被编写成在单个对象上的 CRUD(创建、检索、更新和删除)操作。如果是这种情况,可以简单地映射到一个 RESTful 接口:只需将 EJB 会话 bean 接口或 JAX-WS 接口重新实现为 JAX-WS 接口。为此,您可能需要将对象表示转换成 JSON,但这通常不是很困难的,尤其在您已经使用了 JAX-B 进行序列化时。

在不是一组简单的 CRUD 操作的情况下(比如,转账),那么,您可以应用一些不同的方法来构造 RESTful 服务(比如构建 /accounts/transfer 等简单的功能服务),实现 Command 的异体模式。

第 3 种情况:简单的 Servlet/JSP 接口:许多 Java 程序其实只是连接到数据库表的简单的 Servlet / JSP 前端。它们可能完全没有所谓的 “域对象” 层,特别是在它们遵循 Active Record 等设计模式时。在这种情况下,创建域层,然后可以将它表示为一个 RESTful 服务,这是一个良好的开端。通过应用域驱动的设计 (Domain Driven Design),确定您的域对象,这将帮助您确定缺少的域服务层。一旦构建了域层(并将每一个新的服务包装自己的 WAR),您就可以重构现有的 Servlet / JSP 应用程序来使用新的服务,或者您也可以构建一个全新的界面,也许使用 JavaScript、HTML5 和 CSS,或者作为原生移动应用程序。

第 3 步. 重构数据

一旦构建并重新打包在上述三种情况下定义的小服务,您可能会希望将注意力转移到可能是采用微服务的最困难的问题:重构作为您的应用程序的构建基础的数据结构。我们将在本系列的第 2 部分更深入地探讨这个难题。但在最简单的情况下,也可以遵循一些规则:

1.数据孤岛:从查看您的代码使用的数据库表开始。如果您使用的表独立于其他所有表,或者通过关系联接的几个表进入一个 “孤岛”,那么您可以只将那些表从数据设计中拆分出来。完成这项工作后,您就可以考虑采用适当的服务选项。

例如,您想留在 SQL 中,或许可以考虑从重量级的企业级数据库(如 Oracle)迁移到一个较小的自包含数据库(比如 MySQL)?或者,可以考虑用 NoSQL 数据库来取代 SQL 数据库?该问题的答案取决于您对数据执行的实际查询类型。如果大多数的查询都是对 “主” 键的简单查询,那么一个 “键-值” 数据库或文档数据库就能很好地满足您的要求。另一方面,如果您确实有变化很大的复杂联接(例如,您的查询是不可预测的),那么,继续用 SQL 可能是您最好的选择。

2.批量数据更新:如果只有几个关系,而且您决定将数据迁移到 NoSQL 数据库,那么可以考虑是否只对现有的数据库做一个批量更新。通常情况下,在考虑表之间的关系时,没有将时间因素考虑在内;它们可能并不需要始终是最新的。每隔几个小时运行一次的数据转储/加载方法在许多情况下都是可行的。

3.表非标准化:如果您对其他表的关系较多,您可以重构(或用 DBA 术语,“非标准化”)表。现在,讨论这个话题也会让许多数据库管理员发怒。不过,如果退一步讲,您的团队是一个整体,所以应该想想,为什么要开始进行数据标准化。通常情况下,采用高度标准化架构的原因是为了减少重复,从而节省空间,因为磁盘空间很昂贵。然而,情况已发生改变。现在,我们要优化的是查询时间,而非标准化则是实现这个目标的一个简单方法。

企业借助有效的应用程序重构微服务的3大步骤

第 1 步. 重新打包应用程序

最好的起点是,重新检查您的 Java 应用程序打包结构,采用一些新的打包实践,然后再开始修改代码。在 21 世纪初,我们开始构建一些越来越大的 EAR 文件,以包含我们的逻辑应用程序。然后,我们将这些 EAR 文件部署到服务器场中的每个 WebSphere® Application Server 上。问题是,这种做法试图对应用程序的每段代码都使用相同的部署时间表和相同的物理服务器。任何改变都意味着要重新测试一切,这使得任何改变都变得过于昂贵,不在考虑范围之内。

下面是您需要开始运用的三项原则:

1.拆分 EAR:不要将所有相关的 WAR 打包到一个 EAR 中,而是将它们拆分成独立的 WAR。这可能涉及到一些小的代码改动,或者更可能的是,如果您将应用程序的上下文根改成是分开的,将会涉及要修改静态的内容。

2.应用 “每服务容器 (Container per service)”:接下来,应用 “每服务容器” 模式,将每个 WAR 部署到它自己的 Liberty 服务器中,最好是在它自己的容器中(比如一个 Docker 容器或一个 Bluemix 即时运行时)。然后,您可以独立地扩展容器。

3.独立地构建、部署和管理 :一旦进行了拆分,您就可以通过自动化的 DevOps 管道(如 IBM DevOps Pipeline Service)独立地管理每个 WAR。这是获得持续交付的优势的一个步骤。

您可以看到运用这三项原则的效果:

第 2 步. 重构代码

现在,您的部署策略已经细化到了独立 WAR 的层次,您可以开始寻找机会将 WAR 重构为更精细的水平。以下有三种情况,您可以在其中找到机会重构代码,以适应独立包装微服务的包装方法。

第 1 种情况:现有的 REST 或 JMS 服务:这是迄今为止最简单的重构情况。您可能已经有一些服务可以兼容微服务架构,或者可以让它们变得兼容。首先从 WAR 中清理出所有 REST 或简单的 JMS 服务,然后将每个服务部署为它自己的 WAR。在这个层面上,配套 JAR 文件的副本是没问题的;主要仍然是包装问题。

第 2 种情况:现有的 SOAP 或 EJB 服务:如果您已拥有一些服务,它们可能是遵循某种功能方法(比如 Service Façade 模式)构建的。在这种情况下,以功能为基础的服务设计通常可以被重构为基于资产的服务设计。这是因为,在许多情况下,Service Façade 中的功能最初都被编写成在单个对象上的 CRUD(创建、检索、更新和删除)操作。如果是这种情况,可以简单地映射到一个 RESTful 接口:只需将 EJB 会话 bean 接口或 JAX-WS 接口重新实现为 JAX-WS 接口。为此,您可能需要将对象表示转换成 JSON,但这通常不是很困难的,尤其在您已经使用了 JAX-B 进行序列化时。

在不是一组简单的 CRUD 操作的情况下(比如,转账),那么,您可以应用一些不同的方法来构造 RESTful 服务(比如构建 /accounts/transfer 等简单的功能服务),实现 Command 的异体模式。

第 3 种情况:简单的 Servlet/JSP 接口:许多 Java 程序其实只是连接到数据库表的简单的 Servlet / JSP 前端。它们可能完全没有所谓的 “域对象” 层,特别是在它们遵循 Active Record 等设计模式时。在这种情况下,创建域层,然后可以将它表示为一个 RESTful 服务,这是一个良好的开端。通过应用域驱动的设计 (Domain Driven Design),确定您的域对象,这将帮助您确定缺少的域服务层。一旦构建了域层(并将每一个新的服务包装自己的 WAR),您就可以重构现有的 Servlet / JSP 应用程序来使用新的服务,或者您也可以构建一个全新的界面,也许使用 JavaScript、HTML5 和 CSS,或者作为原生移动应用程序。

第 3 步. 重构数据

一旦构建并重新打包在上述三种情况下定义的小服务,您可能会希望将注意力转移到可能是采用微服务的最困难的问题:重构作为您的应用程序的构建基础的数据结构。我们将在本系列的第 2 部分更深入地探讨这个难题。但在最简单的情况下,也可以遵循一些规则:

1.数据孤岛:从查看您的代码使用的数据库表开始。如果您使用的表独立于其他所有表,或者通过关系联接的几个表进入一个 “孤岛”,那么您可以只将那些表从数据设计中拆分出来。完成这项工作后,您就可以考虑采用适当的服务选项。

例如,您想留在 SQL 中,或许可以考虑从重量级的企业级数据库(如 Oracle)迁移到一个较小的自包含数据库(比如 MySQL)?或者,可以考虑用 NoSQL 数据库来取代 SQL 数据库?该问题的答案取决于您对数据执行的实际查询类型。如果大多数的查询都是对 “主” 键的简单查询,那么一个 “键-值” 数据库或文档数据库就能很好地满足您的要求。另一方面,如果您确实有变化很大的复杂联接(例如,您的查询是不可预测的),那么,继续用 SQL 可能是您最好的选择。

2.批量数据更新:如果只有几个关系,而且您决定将数据迁移到 NoSQL 数据库,那么可以考虑是否只对现有的数据库做一个批量更新。通常情况下,在考虑表之间的关系时,没有将时间因素考虑在内;它们可能并不需要始终是最新的。每隔几个小时运行一次的数据转储/加载方法在许多情况下都是可行的。

3.表非标准化:如果您对其他表的关系较多,您可以重构(或用 DBA 术语,“非标准化”)表。现在,讨论这个话题也会让许多数据库管理员发怒。不过,如果退一步讲,您的团队是一个整体,所以应该想想,为什么要开始进行数据标准化。通常情况下,采用高度标准化架构的原因是为了减少重复,从而节省空间,因为磁盘空间很昂贵。然而,情况已发生改变。现在,我们要优化的是查询时间,而非标准化则是实现这个目标的一个简单方法。

  • 发表于:
  • 原文链接http://kuaibao.qq.com/s/20171224B08W2X00?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券