微服务体系结构已经成为现代应用程序开发的实际选择。虽然它解决了某些问题,但它不是一颗银弹。它也有一些缺点,在使用这种体系结构时,有许多问题必须解决。这就需要学习这些问题中的通用模式,并使用可重用的解决方案来解决它们。因此,需要讨论微服务的设计模式。在深入研究设计模式之前,我们需要了解微服务体系结构的构建原则:
1.可伸缩性
2.可用性
3.弹性
4.独立的,自主的
5.分散治理
6.故障隔离
7.自动预配
8.通过 DevOps 持续交付
应用所有这些原则带来了一些挑战和问题。让我们讨论这些问题和它们的解决方案。
3 数据库模式
a、每个服务一个数据库
问题
如何为微服务定义数据库体系结构是一个问题。以下是需要解决的问题:
1.服务必须松散耦合。它们可以独立地开发、部署和扩展。
2.业务事务可能强制跨多个服务的不变量。
3.一些业务事务需要查询由多个服务拥有的数据。
4.数据库有时必须复制和切分,以便进行扩展。
5.不同的服务有不同的数据存储需求。
解决方案
为了解决上述问题,每个微服务必须设计一个数据库;这项服务必须是私人的。它只能由 microservice API 访问。其他服务不能直接访问它。例如,对于关系数据库,我们可以使用针对服务的私有表、针对服务的模式或针对服务的数据库-服务器。每个微服务都应该有一个单独的数据库 id,以便能够提供单独的访问,以设置障碍,并防止它使用其他服务表。
b、每个服务共享数据库
问题
我们已经讨论过,每个服务有一个数据库对于微服务来说是理想的,但是当应用程序是 greenfield 并且可以用 DDD 开发时,这是可能的。但如果应用程序是一个整体,并试图进入微服务,反规范化不是那么容易。在这种情况下,什么是合适的体系结构?
解决方案
每个服务共享数据库并不理想,但这是上述场景的有效解决方案。大多数人认为这是一种针对微服务的反模式,但对于棕地应用程序来说,这是将应用程序分解为更小的逻辑部分的良好开端。这不应该应用于绿地应用。在这种模式中,一个数据库可以与多个微服务对齐,但必须限制在 2-3 个最大值,否则,伸缩性、自主性和独立性将难以执行。
c、命令查询责任隔离(CQRS)
问题
一旦我们实现了每个服务的数据库,就需要进行查询,这需要来自多个服务的联合数据——这是不可能的。那么,我们如何在微服务体系结构中实现查询呢?
解决方案
CQRS 建议将应用程序分为两部分——命令端和查询端。命令端处理创建、更新和删除请求。查询端通过使用物化视图来处理查询部分。事件源模式通常用于为任何数据更改创建事件。物化视图通过订阅事件流来保持更新。
d、Saga 模式
问题
当每个服务都有自己的数据库和跨越多个服务的业务事务时,我们如何确保服务之间的数据一致性?例如,对于客户有信用限额的电子商务应用程序,应用程序必须确保新订单不会超过客户的信用限额。由于订单和客户位于不同的数据库中,应用程序不能简单地使用本地 ACID 事务。
解决方案
Saga 代表由几个子请求组成的高级业务流程,每个子请求在一个服务中更新数据。当请求失败时,每个请求都有一个补偿请求执行。它可以通过两种方式实现:
编排——当没有中央协调时,每个服务产生并监听另一个服务的事件,并决定是否应该采取行动。
编配——编配者(对象)负责传奇的决策制定和业务逻辑的排序。
4 可观测性模式
a、日志聚合
问题
考虑一个用例,其中应用程序由在多台机器上运行的多个服务实例组成。请求通常跨越多个服务实例。每个服务实例以标准化格式生成一个日志文件。我们如何通过日志了解特定请求的应用程序行为?
解决方案
我们需要一个集中的日志记录服务来聚合来自每个服务实例的日志。用户可以搜索和分析日志。它们可以配置当日志中出现某些消息时触发的警报。例如,PCF 确实有 Loggeregator,它从 PCF 平台的每个组件(路由器、控制器、diego 等)以及应用程序中收集日志。AWS 云表也做了同样的事情。
b、性能标准
问题
当由于微服务体系结构而导致的服务组合增加时,对事务进行监视就变得非常重要,以便在出现问题时可以监视模式并发送警报。我们应该如何收集指标来监控应用程序性能?
解决方案
需要一个度量服务来收集关于单个操作的统计信息。它应该聚合提供报告和警报的应用程序服务的指标。聚合度量有两种模型:
推送——服务将指标推送到指标服务,例如 NewRelic, AppDynamics
Pull - 度量服务从服务中提取度量指标,例如 Prometheus
c、分布式跟踪
问题
在微服务体系结构中,请求通常跨越多个服务。每个服务通过跨多个服务执行一个或多个操作来处理请求。那么,我们如何跟踪端到端请求来解决问题呢?
解决方案
我们需要一种服务
分配每个外部请求一个唯一的外部请求 id。
将外部请求 id 传递给所有服务。
在所有日志消息中包含外部请求 id。
记录在集中服务中处理外部请求时执行的请求和操作的信息(例如,开始时间、结束时间)。
Spring Cloud Slueth 以及 Zipkin server 都是通用实现。
d、健康检查
问题
当实现了微服务体系结构时,服务可能会启动,但无法处理事务。在这种情况下,如何确保请求不会转到那些失败的实例?使用负载平衡模式实现。
解决方案
每个服务都需要有一个端点,可以用来检查应用程序的健康状况,比如/health。这个 API 应该检查主机的状态、到其他服务/基础设施的连接以及任何特定的逻辑。
Spring Boot Actuator 确实实现了一个/health 端点,并且该实现也可以自定义。
5 横切关注点的模式
a、外部配置
问题
服务通常也调用其他服务和数据库。对于开发、QA、UAT、prod 等每个环境,端点 URL 或某些配置属性可能不同。任何这些属性的更改都可能需要重新构建和重新部署服务。如何避免对配置更改进行代码修改?
解决方案
外部化所有配置,包括端点 url 和凭证。应用程序应该在启动或运行时加载它们。
Spring Cloud config server 提供了将属性外部化到 GitHub 并将其作为环境属性加载的选项。应用程序可以在启动时访问它们,也可以在不重启服务器的情况下刷新它们。
b、服务发现模式
问题
当微服务出现的时候,我们需要解决一些关于调用服务的问题:
1.使用容器技术,IP 地址被动态分配给服务实例。每次地址更改时,使用者服务可能会中断,并需要手动更改。
2.每个服务 URL 都必须被使用者记住并成为紧密耦合的。
那么消费者或路由器如何知道所有可用的服务实例和位置呢?
解决方案
需要创建一个服务注册中心,以保存每个生产者服务的元数据。服务实例在启动时应该注册到注册中心,在关闭时应该注销注册。使用者或路由器应查询注册表并找出服务的位置。注册中心还需要对生产者服务进行健康检查,以确保只有服务的工作实例可以通过它使用。有两种类型的服务发现:客户端和服务器端。客户端发现的一个例子是 Netflix Eureka,服务器端发现的一个例子是 AWS ALB。
c、断路器模式
问题
服务通常调用其他服务来检索数据,下游服务可能会停机。这样做有两个问题:首先,请求将继续使用 down 服务,耗尽网络资源并降低性能。其次,用户体验将是糟糕的和不可预测的。如何避免级联服务故障并优雅地处理故障?
解决方案
使用者应该通过代理调用远程服务,代理的行为类似于断路器。当连续故障数超过阈值时,断路器跳闸,在超时期间,所有调用远程服务的尝试都会立即失败。超时过期后,断路器允许有限数量的测试请求通过。如果这些请求成功,断路器将恢复正常工作。否则,如果出现故障,超时周期将再次开始。
Netflix Hystrix 是断路器模式的良好实现。它还可以帮助您定义一个备用机制,可以使用断路器跳闸。这提供了更好的用户体验。
d、蓝绿部署模式
问题
使用微服务体系结构,一个应用程序可以有许多微服务。如果我们停止所有服务,然后部署一个增强版本,停机时间将是巨大的,并可能影响业务。此外,回滚将是一场噩梦。我们如何避免或减少部署期间服务的停机时间?
解决方案
可以实现蓝绿色部署策略以减少或消除停机时间。它通过运行两个相同的生产环境(蓝色和绿色)来实现这一点。让我们假设绿色是现有的活动实例,蓝色是应用程序的新版本。在任何时候,只有一个环境是 live, live 环境服务于所有生产流量。所有云平台都提供了实现蓝绿色部署的选项。
与微服务体系结构一起使用的还有许多其他模式,比如 Sidecar、链式微服务、分支微服务、事件源模式、持续交付模式等等。随着我们在微服务方面获得更多的经验,这个名单还在不断增长。我现在停下来是为了了解您正在使用的微服务模式。
总结
在本篇中,我们给大家介绍了数据库模式、可观测性模式和横切关注点的模式。希望对大家在理解微服务方面有所帮助。
本文转载自公众号 360 云计算(ID:hulktalk)。
原文链接:
https://mp.weixin.qq.com/s/9yNL3fpnV1-Wk3Dz4GohFw
评论