Spring微服务实战第2章 使用Spring Boot构建微服务

第2章 使用Spring Boot构建微服务

基于微服务的架构具有以下特点。

  • 有约束的——微服务具有范围有限的单一职责集。微服务遵循UNIX的理念,即应用程序是服务的集合,每个服务只做一件事,并只做好一件事。
  • 松耦合的——基于微服务的应用程序是小型服务的集合,服务之间使用非专属调用协议(如HTTP和REST)通过非特定实现的接口彼此交互。与传统的应用程序架构相比,只要服务的接口没有改变,微服务的所有者可以更加自由地对服务进行修改。
  • 抽象的——微服务完全拥有自己的数据结构和数据源。微服务所拥有的数据只能由该服务修改。可以锁定微服务数据的数据库访问控制,仅允许该服务访问它。
  • 独立的——微服务应用程序中的每个微服务可以独立于应用程序中使用的其他服务进行编译和部署。这意味着,与依赖更重的单体应用程序相比,这样对变化进行隔离和测试更容易。

为什么这些微服务架构属性对基于云的开发很重要?基于云的应用程序通常有以下特点。

  • 拥有庞大而多样化的用户群——不同的客户需要不同的功能,他们不想在开始使用这些功能之前等待漫长的应用程序发布周期。微服务允许功能快速交付,因为每个服务的范围很小,并通过一个定义明确的接口进行访问。
  • 极高的运行时间要求——由于微服务的分散性,基于微服务的应用程序可以更容易地将故障和问题隔离到应用程序的特定部分之中,而不会使整个应用程序崩溃。这可以减少应用程序的整体宕机时间,并使它们对问题更有抵御能力。
  • 不均匀的容量需求——在企业数据中心内部部署的传统应用程序通常具有一致的使用模式,这些模式会随着时间的推移而定期出现,这使这种类型的应用程序的容量规划变得很简单。但在一个基于云的应用中,Twitter上的一条简单推文或Slashdot上的一篇文章就能够极大带动对基于云计算的应用的需求。
  • 因为微服务应用程序被分解成可以彼此独立部署的小组件,所以能够更容易将重点放在正处于高负载的组件上,并将这些组件在云中的多个服务器上进行水平伸缩。

本章的内容会包含在业务问题中构建和识别微服务的基础知识,构建微服务的骨架,然后理解在生产环境中成功部署和管理微服务的运维属性。

要想成功设计和构建微服务,开发人员需要像警察向目击证人讯问犯罪活动一样着手处理微服务。即使每个证人看到同一事件发生,他们对犯罪活动的解释也是根据他们的背景、他们所看重的东西(例如,给予他们动机的东西),以及在那个时刻目睹这个事件所带来的环境压力塑造出来的。每个参与者都有他们自己认为重要的视角(和偏见)。

就像一名成功的警察试图探寻真相一样,构建一个成功的微服务架构的过程需要结合软件开发组织内多个人的视角。尽管交付整个应用程序需要的不仅仅是技术人员,但我相信,成功的微服务开发的基础是从以下3个关键角色的视角开始的。

  • 架构师——架构师的工作是看到大局,了解应用程序如何分解为单个微服务,以及微服务如何交互以交付解决方案。
  • 软件开发人员——软件开发人员编写代码并详细了解如何将编程语言和该语言的开发框架用于交付微服务。
  • DevOps工程师——DevOps工程师不仅为生产环境而且为所有非生产环境提供服务部署和管理的智慧。DevOps工程师的口号是:保障每个环境中的一致性可重复性

本章将演示如何从这些角色的视角使用Spring Boot和Java设计和构建一组微服务。到本章结束时,读者将有一个可以打包并部署到云的服务。

2.1 架构师的故事:设计微服务架构

架构师在软件项目中的作用是提供待解决问题的工作模型。架构师的工作是提供脚手架,开发人员将根据这些脚手架构建他们的代码,使应用程序所有部件都组合在一起。

在构建微服务架构时,项目的架构师主要关注以下3个关键任务:

(1)分解业务问题;

(2)建立服务粒度;

(3)定义服务接口。

2.1.1 分解业务问题

面对复杂性,大多数人试图将他们正在处理的问题分解成可管理的块。因为这样他们就不必努力把问题的所有细节都考虑进来。他们将问题抽象地分解成几个关键部分,然后寻找这些部分之间存在的关系。

在微服务架构中,架构师将业务问题分解成代表离散活动领域的块。这些块封装了与业务域特定部分相关联的业务规则和数据逻辑。

虽然我们希望微服务封装执行单个事务的所有业务规则,但这并不总是行得通。我们经常会遇到需要跨业务领域不同部分的一组微服务来完成整个事务的情况。架构师通过查看数据域中那些不适合放到一起的地方来划分一组微服务的服务边界。

例如,架构师可能会看到代码执行的业务流程,并意识到它们同时需要客户和产品信息。存在两个离散的数据域时,通常就意味着需要使用多个微服务。业务事务的两个不同部分如何交互通常成为微服务的服务接口。

分离业务领域是一门艺术,而不是非黑即白的科学。读者可以使用以下指导方针将业务问题识别和分解为备选的微服务。

(1)描述业务问题,并聆听用来描述问题的名词。在描述问题时,反复使用的同一名词通常意味着它们是核心业务领域并且适合创建微服务。第1章中EagleEye域的目标名词可能会是合同许可证资产

(2)注意动词。动词突出了动作,通常代表问题域的自然轮廓。如果发现自己说出“事务X需要从事物A和事物B获取数据”这样的话,通常表明多个服务正在起作用。如果把注意动词的方法应用到EagleEye上,那么就可能会查找像“来自桌面服务的Mike安装新PC时,他会查找软件X可用的许可证数量,如果有许可证,就安装软件。然后他更新了跟踪电子表格中使用的许可证的数量”这样的陈述句。这里的关键动词是查找和更新。

(3)寻找数据内聚。将业务问题分解成离散的部分时,要寻找彼此高度相关的数据。如果在会话过程中,突然读取或更新与迄今为止所讨论的内容完全不同的数据,那么就可能还存在其他候选服务。微服务应完全拥有自己的数据。

让我们将这些指导方针应用到现实世界的问题中。第1章介绍了一种名为EagleEye的现有软件产品,该软件产品用于管理软件资产,如软件许可证和安全套接字层(SSL)证书。这些软件资产被部署到组织中的各种服务器上。

EagleEye是一个传统的单体Web应用程序,部署在位于客户数据中心内的J2EE应用程序服务器。我们的目标是将现有的单体应用程序梳理成一组服务。

首先,我们要采访EagleEye应用程序的所有用户,并讨论他们是如何交互和使用EagleEye的。图2-1描述了与不同业务客户进行的对话的总结。通过查看EagleEye的用户是如何与应用程序进行交互的,以及如何将应用程序的数据模型分解出来,可以将EagleEye问题域分解为以下备选微服务。

image-20210901140456099

图2-1 采访EagleEye用户,了解他们如何做日常工作

图2-1强调了与业务用户对话时出现的一些名词和动词。因为这是现有的应用程序,所以可以查看应用程序并将主要名词映射到物理数据模型中的表。现有应用程序可能有数百张表,但每张表通常会映射回一组逻辑实体。

图2-2展示了基于与EagleEye客户对话的简化数据模型。基于业务对话和数据模型,备选微服务是组织、许可证、合同和资产服务。

image-20210901140657425

图2-2 简化的EagleEye数据模型

2.1.2 建立服务粒度

拥有了一个简化的数据模型,就可以开始定义在应用程序中需要哪些微服务。根据图2-2中的数据模型,可以看到潜在的4个微服务基于以下元素:

  • 资产;
  • 许可证;
  • 合同;
  • 组织。

我们的目标是将这些主要的功能部件提取到完全独立的单元中,这些单元可以独立构建和部署。但是,从数据模型中提取服务需要的不只是将代码重新打包到单独的项目中,还涉及梳理出服务访问的实际数据库表,并且只允许每个单独的服务访问其特定域中的表。图2-3展示了应用程序代码和数据模型如何被“分块”到各个部分。

image-20210901140835537

图2-3 将数据模型作为把单体应用程序分解为微服务的基础

将问题域分解成不同的部分后,开发人员通常会发现自己不确定是否为服务划分了适当的粒度级别。一个太粗粒度或太细粒度的微服务将具有很多的特征,我们将在稍后讨论。

构建微服务架构时,粒度的问题很重要,可以采用以下思想来确定正确的解决方案。

(1)开始的时候可以让微服务涉及的范围更广泛一些,然后将其重构到更小的服务——在开始微服务旅程之初,容易出现的一个极端情况就是将所有的事情都变成微服务。但是将问题域分解为小型的服务通常会导致过早的复杂性,因为微服务变成了细粒度的数据服务。

(2)重点关注服务如何相互交互——这有助于建立问题域的粗粒度接口。从粗粒度重构到细粒度是比较容易的。

(3)随着对问题域的理解不断增长,服务的职责将随着时间的推移而改变——通常来说,当需要新的应用功能时,微服务就会承担起职责。最初的微服务可能会发展为多个服务,原始的微服务则充当这些新服务的编排层,负责将应用的其他部分的功能封装起来。

糟糕的微服务的“味道”

如何知道微服务的划分是否正确?如果微服务过于粗粒度,可能会看到以下现象。

服务承担过多的职责——服务中的业务逻辑的一般流程很复杂,并且似乎正在执行一组过于多样化的业务规则。

该服务正在跨大量表来管理数据——微服务是它管理的数据的记录系统。如果发现自己将数据持久化存储到多个表或接触到当前数据库以外的表,那么这就是一条服务过于粗粒度的线索。我喜欢使用这么一个指导方针——微服务应该不超过3~5个表。再多一点,服务就可能承担了太多的职责。

测试用例太多——随着时间的推移,服务的规模和职责会增长。如果一开始有一个只有少量测试用例的服务,到了最后该服务需要数百个单元测试用例和集成测试用例,那么就可能需要重构。

如果微服务过于细粒度呢?

问题域的一部分微服务像兔子一样繁殖——如果一切都成为微服务,将服务中的业务逻辑组合起来会变得复杂和困难,因为完成一项工作所需的服务数量会快速增长。一种常见的“坏味道”出现在应用程序有几十个微服务,并且每个服务只与一个数据库表进行交互时。

微服务彼此间严重相互依赖——在问题域的某一部分中,微服务相互来回调用以完成单个用户请求。

微服务成为简单CRUD(Create,Read,Update,Delete)服务的集合——微服务是业务逻辑的表达,而不是数据源的抽象层。如果微服务除了CRUD相关逻辑之外什么都不做,那么它们可能被划分得太细粒度了。

应该通过演化思维的过程来开发一个微服务架构,在这个过程中,你知道不会第一次就得到正确的设计。这就是最好从一组粗粒度的服务而不是一组细粒度的服务开始的原因。同样重要的是,不要对设计带有教条主义。我们可能会面临两个单独的服务之间交互过于频繁,或者服务的域之间不存在明确的边界这样的物理约束,当面临这样的约束时,需要创建一个聚合服务来将数据连接在一起。

最后,采取务实的做法并进行交付,而不是浪费时间试图让设计变得完美,最终导致没有东西可以展现你的努力。

2.1.3 互相交流:定义服务接口

架构师需要关心的最后一部分,是应用程序中的微服务该如何彼此交流。使用微服务构建业务逻辑时,服务的接口应该是直观的,开发人员应该通过学习应用程序中的一两个服务来获得应用程序中所有服务的工作节奏。

一般来说,可使用以下指导方针思考服务接口设计。

(1)拥抱REST的理念——REST对服务的处理方式是将HTTP作为服务的调用协议并使用标准HTTP动词(GET、PUT、POST和DELETE)。围绕这些HTTP动词对基本行为进行建模。

(2)使用URI来传达意图——用作服务端点的URI应描述问题域中的不同资源,并为问题域内的资源的关系提供一种基本机制。

(3)请求和响应使用JSON——JavaScript对象表示法(JavaScript Object Notation,JSON)是一个非常轻量级的数据序列化协议,并且比XML更容易使用。

(4)使用HTTP状态码来传达结果——HTTP协议具有丰富的标准响应代码,以指示服务的成功或失败。学习这些状态码,并且最重要的是在所有服务中始终如一地使用它们。

所有这些指导方针都是为了完成一件事,那就是使服务接口易于理解和使用。我们希望开发人员坐下来查看一下服务接口就能开始使用它们。如果微服务不容易使用,开发人员就会另辟道路,破坏架构的意图。

2.2 何时不应该使用微服务

本书用这一章来谈论为什么微服务是构建应用程序的强大的架构模式。但是,本书还没有提及什么时候不应该使用微服务来构建应用程序。接下来,让我们了解一下其中的考量因素:

(1)构建分布式系统的复杂性;

(2)虚拟服务器/容器散乱;

(3)应用程序的类型;

(4)数据事务和一致性。

2.2.1 构建分布式系统的复杂性

因为微服务是分布式和细粒度(小)的,所以它们在应用程序中引入了一层复杂性,而在单体应用程序中就不会出现这样的情况。微服务架构需要高度的运维成熟度。除非组织愿意投入高分布式应用程序获得成功所需的自动化和运维工作(监控、伸缩),否则不要考虑使用微服务。

2.2.2 服务器散乱

微服务最常用的部署模式之一就是在一个服务器上部署一个微服务实例。在基于微服务的大型应用程序中,最终可能需要50~100台服务器或容器(通常是虚拟的),这些服务器或容器必须单独搭建和维护。即使在云中运行这些服务的成本较低,管理和监控这些服务器的操作复杂性也是巨大的。

注意

必须对微服务的灵活性与运行所有这些服务器的成本进行权衡。

2.2.3 应用程序的类型

微服务面向可复用性,并且对构建需要高度弹性和可伸缩性的大型应用程序非常有用。这就是这么多云计算公司采用微服务的原因之一。如果读者正在构建小型的、部门级的应用程序或具有较小用户群的应用程序,那么搭建一个分布式模型(如微服务)的复杂性可能太昂贵了,不值得。

2.2.4 数据事务和一致性

开始关注微服务时,需要考虑服务的数据使用模式以及服务消费者如何使用它们。微服务包装并抽象出少量的表,作为执行“操作型”任务的机制,如创建、添加和执行针对存储的简单(非复杂的)查询,其工作效果很好。

如果应用程序需要跨多个数据源进行复杂的数据聚合或转换,那么微服务的分布式性质会让这项工作变得很困难。这样的微服务总是承担太多的职责,也可能变得容易受到性能问题的影响。

还要记住,在微服务间执行事务没有标准。如果需要事务管理,那就需要自己构建逻辑。另外,如第7章所述,微服务可以通过使用消息进行通信。消息传递在数据更新中引入了延迟。应用程序需要处理最终的一致性,数据的更新可能不会立即出现。

2.3 开

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值