架构师需要关心的最后一部分,是应用程序中的微服务该如何彼此交流。使用微服务构建业务逻辑时,服务的接口应该是直观的,开发人员应该通过学习应用程序中的一两个服务来获得应用程序中所有服务的工作节奏。
一般来说,可使用以下指导方针思考服务接口设计。
(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 开发人员的故事:用Spring Boot和Java构建微服务
在构建微服务时,从概念到实现,需要视角的转换。具体来说,开发人员需要建立一个实现应用程序中每个微服务的基本模式。虽然每项服务都将是独一无二的,但我们希望确保使用的是一个移除样板代码的框架,并且微服务的每个部分都采用相同的布局。
在本节中,我们将探讨开发人员从EagleEye域模型构建许可证微服务的优先事项。许可证服务将使用Spring Boot编写。Spring Boot是标准Spring库之上的一个抽象层,它允许开发人员快速构建基于Groovy和Java的Web应用程序和微服务,比成熟的Spring应用程序能够节省大量的配置。
对于许可证服务示例,这里将使用Java作为核心编程语言并使用Apache Maven作为构建工具。
在接下来的几节中,我们将要完成以下几项工作。
(1)构建微服务的基本框架并构建应用程序的Maven脚本。
(2)实现一个Spring引导类,它将启动用于微服务的Spring容器,并启动类的所有初始化工作。
(3)实现映射端点的Spring Boot控制器类,以公开服务的端点。
2.3.1 从骨架项目开始
首先,要为许可证服务创建一个骨架项目。读者可以从本章的GitHub存储库拉取源代码,
也可以创建具有以下目录结构的许可证服务项目目录:
licensing-service
src/main/java/com/thoughtmechanix/licenses
controllers
model
services
resources
一旦拉取或创建了这个目录结构,就可以开始为项目编写Maven脚本。这就是位于项目根目录下的pom.xml文件。代码清单2-1展示了许可证服务的Maven POM文件。
代码清单2-1 许可证服务的Maven POM文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns=http://maven.apache.org/POM/4.0.0
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
➥ http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.thoughtmechanix</groupId>
<artifactId>licensing-service</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>jar</packaging>
<name>EagleEye Licensing Service</name>
<description>Licensing Service</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId> ←告诉Maven包含Spring Boot起步工具包依赖项
<version>1.4.4.RELEASE</version>
<relativePath/>
</parent>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId> ← 告诉Maven包含Spring Boot Web依赖项
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-actuator</artifactId> ← 告诉Maven包含Spring Actuator依赖项
</dependency>
</dependencies>
<!—- 注意:某些构建属性和Docker构建插件已从此pom中的pom.xml中排除掉了(GitHub存储库的
源代码中并没有移除),因为它们与这里的讨论无关。
-->
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId> ← 告诉Maven包含Spring特定的Maven插件,用于构建和部署Spring Boot应用程序
</plugin>
</plugins>
</build>
</project>
2.3.1 从骨架项目开始
《Spring微服务实战》第2章使用Spring Boot构建微服务,Spring,本章将演示如何从这些角色的视角使用Spring Boot和Java设计和构建一组微服务。到本章结束时,读者将有一个可以打包并部署到云的服务。本节为大家介绍从骨架项目开始。
作者:陈文辉 译来源:人民邮电出版社|2018-05-23 14:30
收藏
分享
2.3.1 从骨架项目开始
首先,要为许可证服务创建一个骨架项目。读者可以从本章的GitHub存储库拉取源代码,也可以创建具有以下目录结构的许可证服务项目目录:
licensing-service
src/main/java/com/thoughtmechanix/licenses
controllers
model
services
resources
一旦拉取或创建了这个目录结构,就可以开始为项目编写Maven脚本。这就是位于项目根目录下的pom.xml文件。代码清单2-1展示了许可证服务的Maven POM文件。
代码清单2-1 许可证服务的Maven POM文件
1. <?xml version="1.0" encoding="UTF-8"?>
2. <project xmlns=http://maven.apache.org/POM/4.0.0
3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
5. ➥ http://maven.apache.org/xsd/maven-4.0.0.xsd">
6. <modelVersion>4.0.0</modelVersion>
7. <groupId>com.thoughtmechanix</groupId>
8. <artifactId>licensing-service</artifactId>
9. <version>0.0.1-SNAPSHOT</version>
10. <packaging>jar</packaging>
11. <name>EagleEye Licensing Service</name>
12. <description>Licensing Service</description>
13. <parent>
14. <groupId>org.springframework.boot</groupId>
15. <artifactId>spring-boot-starter-parent</artifactId> ⇽--- 告诉Maven包含Spring Boot起步工具包依赖项
16. <version>1.4.4.RELEASE</version>
17. <relativePath/>
18. </parent>
19. <dependencies>
20. <dependency>
21. <groupId>org.springframework.boot</groupId>
22. <artifactId>spring-boot-starter-web</artifactId> ⇽--- 告诉Maven包含Spring Boot Web依赖项
23. </dependency>
24. <dependency>
25. <groupId>org.springframework.boot</groupId>
26. <artifactId>spring-boot-starter-actuator</artifactId> ⇽--- 告诉Maven包含Spring Actuator依赖项
27. </dependency>
28. </dependencies>
29. <!—- 注意:某些构建属性和Docker构建插件已从此pom中的pom.xml中排除掉了(GitHub存储库的
30. 源代码中并没有移除),因为它们与这里的讨论无关。
31. -->
32. <build>
33. <plugins>
34. <plugin>
35. <groupId>org.springframework.boot</groupId>
36. <artifactId>spring-boot-maven-plugin</artifactId> ⇽--- 告诉Maven包含Spring特定的Maven插件,用于构建和部署Spring Boot应用程序
37. </plugin>
38. </plugins>
39. </build>
40. </project>
这里不会详细讨论整个脚本,但是在开始的时候要注意几个关键的地方。Spring Boot被分解成许多个独立的项目。其理念是,如果不需要在应用程序中使用Spring Boot的各个部分,那么就不应该“拉取整个世界”。这也使不同的Spring Boot项目能够独立地发布新版本的代码。为了简化开发人员的开发工作,Spring Boot团队将相关的依赖项目收集到各种“起步”(starter)工具包中。Maven POM的第一部分告诉Maven需要拉取Spring Boot框架的1.4.4版本。
Maven文件的第二部分和第三部分确定了要拉取Spring Web和Spring Actuator起步工具包。这两个项目几乎是所有基于Spring Boot REST服务的核心。读者会发现,服务中构建功能越多,这些依赖项目的列表就会变得越长。
此外,Spring Source还提供了Maven插件,可简化Spring Boot应用程序的构建和部署。第四部分告诉Maven构建脚本安装最新的Spring Boot Maven插件。此插件包含许多附加任务(如spring-boot:run),可以简化Maven和Spring Boot之间的交互。
最后,读者将看到一条注释,说明Maven文件的哪些部分已被删除。为了简化,本书没有在代码清单2-1中包含Spotify Docker插件。
注意
本书的每一章都包含用于构建和部署Docker容器的Docker文件。读者可以在每章代码部分的README.md文件中找到如何构建这些Docker镜像的详细信息。