写点什么

微服务设计模式(下)

2019 年 11 月 20 日

微服务设计模式(下)

微服务体系结构已经成为现代应用程序开发的实际选择。虽然它解决了某些问题,但它不是一颗银弹。它也有一些缺点,在使用这种体系结构时,有许多问题必须解决。这就需要学习这些问题中的通用模式,并使用可重用的解决方案来解决它们。因此,需要讨论微服务的设计模式。在深入研究设计模式之前,我们需要了解微服务体系结构的构建原则:


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


2019 年 11 月 20 日 11:37407

评论

发布
暂无评论
发现更多内容

拥抱K8S系列-06-K8S如何解决docker部署的问题

张无忌

Docker Kubernetes 运维 service

这篇文章,把中国科技的真实底子讲透了

CECBC区块链专委会

中国 科技 产业竞争

JavaScript引擎的事件循环机制是怎样工作的?

Walker

Java 前端 运行时栈帧 事件循环

从外卖员到拼多多30K+程序员,我付出了三年的青春

小Q

Java 学习 程序员 架构 面试

LeetCode题解:232. 用栈实现队列,使用两个栈 入队 - O(1),出队 - 摊还复杂度 O(1),JavaScript,详细注释

Lee Chen

LeetCode 前端进阶训练营

服了,十年运维架构专家的MySQL运维经验,除了实战还是实战

周老师

Java 编程 程序员 架构 面试

数字货币交易所开发方案,交易所源码

13530558032

区块链数字钱包开发,数字钱包app

13530558032

架构师训练营第十四周

Melo

【高并发】Redis如何助力高并发秒杀系统,看完这篇我彻底懂了!!

冰河

redis 多线程 高并发 秒杀 电商超卖

多线程与高并发之锁

彭阿三

多线程 多线程与高并发

不要以为Bug写的好就是好程序员,其实这只占不到15%

小Q

Java 学习 程序员 架构 面试

记一种spring框架的想当然但错误的用法

小明同学

源码分析 最佳实践 Spring Framework bug

oeasy教您玩转linux 010211 牛说 cowsay

o

[翻译]Scalable Go Scheduler Design Doc[Go可扩展调度设计文档]

卓丁

golang golang scheduler Go scheduler

阿里培训官给新入职程序员的25条建议

Java架构师迁哥

基于Goc的Golang代码VSCode实时染色方案

大卡尔

go 测试覆盖率 精准测试

朱嘉明:全球科技革命正在逼近“奇点”,区块链影响未来人类社会的走向

CECBC区块链专委会

人工智能 科技 科技革命

.NET委托,事件和Lambda表达式

AI代笔

LeetCode题解:232. 用栈实现队列,使用两个栈 入队 - O(n), 出队 - O(1),JavaScript,详细注释

Lee Chen

前端进阶训练营

澳门金沙玩赢了钱提现不了异常注单未更新有什么办法处理?

丛林里的余光

异常检测 澳门金沙 提现不了

面试必问亿级流量优化策略之JVM调优,文档视频面试,还不收藏

小Q

Java 程序员 架构 JVM jvm调优

一文解开java中字符串编码的小秘密

程序那些事

java安全编码 java编码指南 UTF编码

USDT承兑支付系统,区块链跨境支付源码

13530558032

MySQL最全整理(面试题+笔记+导图),面试大厂不再被MySql难倒!

Java成神之路

Java MySQL 编程 程序员 面试

甲方日常 13

句子

工作 随笔杂谈 日常

宅家三个月玩转算法,再战字节跳动,字节跳动面试官朝我比了个“ok”

云流

编程 字节跳动 算法 Java 面试

Dubbo-go应用维度注册模型

apache/dubbo-go

dubbo dubbo-go dubbogo

大项目写代码写到晕头转向?敏捷多项目框架解君愁

Philips

敏捷开发 程序设计 软件架构

合约跟单模式系统开发,交易所合约跟单源码

13530558032

大数据任务调度 - 有向无环图(DAG)之拓扑排序

海豚调度

数据结构 大数据任务调度 DAG 拓扑排序 Apache DolphinScheduler

微服务设计模式(下)-InfoQ