天天看点

使用Spring Cloud和Docker构建微服务架构

【编者的话】如何使用Spring Boot、Spring Cloud、Docker和Netflix的一些开源工具来构建一个微服务架构。本文通过使用Spring Boot、Spring Cloud和Docker构建的概念型应用示例,提供了了解常见的微服务架构模式的起点。

我选择了一个老项目作为这个系统的基础,它的后端以前是单一应用。此应用提供了处理个人财务、整理收入开销、管理储蓄、分析统计和创建简单预测等功能。

整个应用分解为三个核心微服务。它们都是可以独立部署的应用,围绕着某些业务功能进行组织。

<a href="http://dockerone.com/uploads/article/20171007/d6db2e5f50a88fa75911e1a078e2dce6.png" target="_blank"></a>

账户服务

包含一般用户输入逻辑和验证:收入/开销记录、储蓄和账户设置。

<a href="http://dockerone.com/uploads/article/20171007/cbfb8a08787af4073723be5d87cda517.png" target="_blank"></a>

统计服务

计算主要的统计参数,并捕获每一个账户的时间序列。数据点包含基于货币和时间段正常化后的值。该数据可用于跟踪账户生命周期中的现金流量动态。

<a href="http://dockerone.com/uploads/article/20171007/65245e0b07a31d009583c416f40359d0.png" target="_blank"></a>

通知服务

存储用户的联系信息和通知设置(如提醒和备份频率)。安排工作人员从其它服务收集所需的信息并向订阅的客户发送电子邮件。

<a href="http://dockerone.com/uploads/article/20171007/3b610b126f71ffbd6b9c1b34a7110b5d.png" target="_blank"></a>

注意

每一个微服务拥有自己的数据库,因此没有办法绕过API直接访问持久数据。

在这个项目中,我使用MongoDB作为每一个服务的主数据库。拥有一个多种类持久化架构(polyglot persistence architecture)也是很有意义的。

<a href="http://dockerone.com/uploads/article/20171007/eb23046d0859325930d8eeb3f552dd36.png" target="_blank"></a>

客户端使用

只需要使用sprng-cloud-starter-config依赖构建Spring Boot应用,自动配置将会完成其它工作。

现在您的应用中不需要任何嵌入的properties,只需要提供有应用名称和配置服务url的bootstrap.yml即可:

使用Spring Cloud Config,您可以动态更改应用配置

动态刷新存在一些限制。@RefreshScope不能和@Configuraion类一同工作,并且不会作用于@Scheduled方法。

fail-fast属性意味着如果Spring Boot应用无法连接到配置服务,将会立即启动失败。当您一起启动所有应用时,这非常有用。

下面有重要的安全提示

在此项目中,我使用密码凭据作为用户授权的授权类型(因为它仅由本地应用UI使用)和客户端凭据作为微服务授权的授权类型。

从客户端来看,一切都与传统的基于会话的授权完全相同。您可以从请求中检索Principal对象、检查用户角色和其它基于表达式访问控制和@PreAuthorize注解的内容。

PiggyMetrics(帐户服务、统计服务、通知服务和浏览器)中的每一个客户端都有一个范围:用于后台服务的服务器、用于浏览器展示的UI。所以我们也可以保护控制器避免受到外部访问,例如:

您可以看到,有三个核心服务。它们向客户端暴露外部API。在现实系统中,这个数量可以非常快速地增长,同时整个系统将变得非常复杂。实际上,一个复杂页面的渲染可能涉及到数百个服务。

理论上,客户端可以直接向每个微服务直接发送请求。但是这种方式是存在挑战和限制的,如果需要知道所有端点的地址,分别对每一段信息执行http请求,将结果合并到客户端。另一个问题是,这不是web友好协议,可能只在后端使用。

另一种常见的架构模式是服务发现。它允许自动检测服务实例的网络位置,由于自动扩展、故障和升级,它可能会动态分配地址。

服务发现的关键部分是注册。我使用Netflix Eureka进行这个项目,当客户端需要负责确定可以用的服务实例(使用注册服务器)的位置和跨平台的负载均衡请求时,Eureka就是客户端发现模式的一个很好的例子。

使用Spring Boot,您可以使用spring-cloud-starter-eureka-server依赖、@EnabledEurekaServer注解和简单的配置属性轻松构建Eureka注册中心(Eureka Registry)。

使用@EnabledDiscoveryClient注解和带有应用名称的bootstrap.yml来启用客户端支持:

现在,在应用启动时,它将向Eureka服务器注册并提供元数据,如主机和端口、健康指示器URL、主页等。Eureka接收来自从属于某服务的每个实例的心跳消息。如果心跳失败超过配置的时间表,该实例将从注册表中删除。

<a href="http://dockerone.com/uploads/article/20171007/38c4fe054ca5b155fad2d25367f204a7.png" target="_blank"></a>

Netflix OSS提供了另一套很棒的工具。

Ribbon

Ribbon是一个客户端负载均衡器,可以很好地控制HTTP和TCP客户端的行为。与传统的负载均衡器相比,每次线上调用都不需要额外的跳跃——您可以直接联系所需的服务。

Hystrix

除了断路器控制,在使用Hystrix,您可以添加一个备用方法,在主命令失败的情况下,该方法将被调用以获取默认值。

Feign

Feign是一个声明式HTTP客户端,能与Ribbon和Hystrix无缝集成。实际上,通过一个spring-cloud-starter-feign依赖和@EnabledFeignClients注解,您可以使用一整套负载均衡器、断路器和HTTP客户端,并附带一个合理的的默认配置。

以下是账户服务的示例:

您需要的只是一个接口

您可以在Spring MVC控制器和Feign方法之间共享@RequestMapping部分

以上示例仅指定所需要的服务ID——statistics-service,这得益于Eureka的自动发现(但显然您可以使用特定的URL访问任何资源)。

让我们看看系统行为在负载下:账户服务调用统计服务和它在一个变化的模拟延迟下的响应。响应超时阈值设置为1秒。

<a href="http://dockerone.com/uploads/article/20171007/7333a6f825e320a86364499ce0b9035c.png" target="_blank"></a>

部署微服务比部署单一的应用的流程要复杂得多,因为它们相互依赖。拥有完全基础设置自动化是非常重要的。我们可以通过持续交付的方式获得以下好处:

随时发布软件的能力。

任何构建都可能最终成为一个发行版本。

构建工件(artifact)一次,根据需要进行部署。

这是一个简单的持续交付工作流程,在这个项目的实现:

<a href="http://dockerone.com/uploads/article/20171007/5177e519e9705885f02acdbc86954cc6.png" target="_blank"></a>

这真的很简单,我建议您尝试一下。请记住,您将要启动8个Spring Boot应用、4个MongoDB实例和RabbitMq。确保您的机器上有4GB的内存。您可以随时通过网关、注册中心、配置、认证服务和账户中心运行重要的服务。

运行之前

安装Docker和Docker Compose。

配置环境变量:CONFIG_SERVICE_PASSWORD, NOTIFICATION_SERVICE_PASSWORD, STATISTICS_SERVICE_PASSWORD, ACCOUNT_SERVICE_PASSWORD, MONGODB_PASSWORD

生产模式

在这种模式下,所有最新的镜像都将从Docker Hub上拉取。只需要复制docker-compose.yml并执行docker-compose up -d即可。

开发模式

如果您想自己构建镜像(例如,在代码中进行一些修改),您需要克隆所有仓库(repository)并使用Mavne构建工件(artifact)。然后,运行docker-compose -f docker-compose.yml -f docker-compose.dev.yml up -d

docker-compose.dev.yml继承了docker-compose.yml,附带额外配置,可在本地构建镜像,并暴露所有容器端口以方便开发。

重要的端点(Endpoint)

localhost:80 —— 网关

localhost:8761 —— Eureka仪表盘

localhost:9000 —— Hystrix仪表盘

localhost:8989 —— Turbine stream(Hystrix仪表盘来源)

localhost:15672 —— RabbitMq管理

此外,服务发现机制在所有应用启动后需要一段时间。在实例、Eureka服务器和客户端在其本地缓存中都具有相同的元数据之前,任何服务都不可用于客户端发现,因此可能需要3次心跳。默认的心跳周期为30秒。

<b>原文发布时间为:</b>2017-10-07

<b>本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。</b>

<b></b>

<b>原文标题:</b><b>使用Spring Cloud和Docker构建微服务架构</b>