145°

微服务模式-同步与异步

了解同步和异步的不同类型的微服务模式,以及每种服务的优势和取舍。

微服务是一种架构范例。在这种架构风格中,小型且独立的组件可以作为一个系统协同工作。尽管其操作复杂性较高,但该范例已被迅速采用。这是因为它有助于将复杂的系统分解为可管理的服务。服务包含微观层面的关注点,例如单一责任,关注点分离,模块化等。

微服务模式是一系列博客。每个博客都将关注微服务的体系结构模式。它将说明可能性并概述适用的情况。所有这些都在考虑到各种系统设计约束之间的相互影响。

通过优锐课的java学习分享,了解到服务间通信和执行流程是分布式系统的基础决策。本质上,它可以是同步的或异步的。两种方法都有其取舍和优势。该博客试图详细剖析各种选择并理解其含义。

外型尺寸

每种实现方式都有权衡。 同时,正在考虑的系统可能有多种尺寸。 在这些约束条件下评估取舍可以帮助我们推理出方法和适用性。 系统的各个方面都会影响系统的执行流程和通信风格。 让我们来看一些。

消费者

系统的使用者可以是外部程序,Web /移动界面,IoT设备等。使用者应用程序通常会与服务器同步处理,并期望接口能够支持该服务器。 还期望用用于消费者的统一接口来掩盖分布式系统的复杂性。 因此,我们的沟通方式必须让我们为之便利。

工作流程管理

对于许多参与服务,业务流程的管理至关重要。它可以是隐式的,并且可以在每个服务处发生,因此保持分布在各个服务之间。或者,它可以是显式的。协调器服务可以负责协调业务流程。

业务流程是两件事的结合。工作流程规范,列出执行顺序和对服务的实际调用。后者与参与服务遵循的通信范式紧密相关。沟通方式和执行流程驱动着协调器的实现。

第三种选择是基于事件编排的设计。这通过每个服务绑定到的事件总线来替代协调器。

所有这些都是在系统中管理工作流程的机制。在本系列的后面,我们将详细介绍工作流管理。但是,在评估和选择交流范式时,我们将在当前上下文中考虑与它们相关的约束。

/写频率偏差

系统的读/写频率可能是其体系结构中的关键因素。 大量读取的系统期望大多数操作同步完成。 一个很好的例子是大规模运行的天气预报服务的公共API。 替代地,繁重的写入系统受益于异步执行。 一个示例就是一个平台,在该平台上,许多IoT设备不断报告数据。 当然,两者之间也有系统。 有时,由于读写偏斜,支持样式很有用。 在其他时候,将读取和写入分为单独的组件可能很有意义。

在研究各种方法时,我们需要保持对这些约束的了解。 这些维度将帮助我们提炼每种实现方式的适用性。

同步

同步通信是一种通信方式,在此方式中,呼叫者等待直到响应可用。这是一种突出且广泛使用的方法。它的概念简单性允许直接实现,使其非常适合大多数情况。

同步通信与HTTP协议紧密相关。但是,其他协议仍然是实现同步通信的同样合理的方式。替代方法的一个很好的例子是RPC调用。每个组件都公开一个其他服务调用的同步接口。

入口点附近的拦截器拦截业务流程请求。然后,它将请求推送到下游服务。本质上,所有后续调用都是同步的。这些调用可以并行或顺序进行,直到处理完成。系统内呼叫的处理方式可能会有所不同。协调器可以显式协调所有呼叫。否则呼叫会在组件之间自然渗透。让我们看一下几种可能的机制。

变化

在同步系统中,架构可以采用几种方法。 这是各种可能性的简要概述。

去中心化和同步

分散和同步的通信样式在入口点拦截流。 拦截器将请求转发到下一步并等待响应。 此循环一直持续到下游,直到所有服务都已完成其执行。 每个服务可以顺序或并行执行一个或多个下游服务。

尽管实现起来很简单,但流细节仍保留在系统中。 这导致组件之间的耦合以执行流程。

呼叫在整个系统中保持同步。 因此,通信风格可以满足同步消费者的期望。 由于工作流程具有分布式性质,因此该方法没有灵活性的余地。 它不太适合易于更改的复杂工作流程。 由于对系统的每个请求都可以同时阻止服务,因此对于具有高读写频率的系统而言,这不是理想的选择。.

 

编排,同步和顺序

同步通信的一种形式是使用中央协调器。 协调器将保留拦截服务。 它使用工作流定义处理传入的请求,并将其转发到下游服务。 每个服务依次反过来响应协调器。 在处理请求之前,协调器一直在对服务进行调用。

在开始列出的限制中,工作流管理在此方法中更加灵活。 工作流程更改仅对业务流程负责,并且具有灵活性。 由于通信是同步的,因此同步使用者可以在没有中介组件的情况下进行通信。 但是,协调器将继续保留所有活动请求。 与其他服务相比,这给协调器带来了更多负担。 它也容易成为单点故障。 这种体系结构的样式仍然适用于重载系统

 

协调,同步和并行

对先前方法的一个小改进是使独立请求并行进行。 这导致更高的效率和性能。 由于这种责任属于编排领域,因此很容易做到。 工作流管理已经集中。 它只需要更改声明即可区分并行调用和顺序调用。

这可以允许更快地执行流。 使用较短的响应时间,协调器可以具有更高的吞吐量。

工作流管理比以前的方法更为复杂。 由于它同时提高了吞吐量和性能,因此仍然可能是一个合理的权衡。 所有这些,同时使消费者保持通信同步。 由于其同步特性,该系统对于重读架构仍然更好。

 

权衡取舍

尽管同步调用更易于掌握,调试和实现,但在分布式设置中仍有一些折衷值得承认。

平衡容量

它需要故意平衡所有服务的容量。 一个组件上的临时突发可能会使其他服务泛滥。 以异步方式,队列可以减轻临时突发。 同步通信缺少这种中介,需要在突发期间匹配服务容量。 否则,可能会导致级联失败。 替代地,诸如断路器的弹性范例可以帮助减轻同步系统中的业务突发。

级联故障的风险

同步通信使上游服务容易受到微服务架构中级联故障的影响。 如果下游服务失败或最差,则需要很长时间才能做出响应,资源可能会很快耗尽。 这可能会导致系统产生多米诺骨牌效应。 可能的缓解策略可能涉及一致的错误处理,合理的连接超时和强制执行SLA。 在同步环境中,不断恶化的服务的影响会立即通过其他服务波动。 如前所述,可以通过实施bulkhead架构或使用断路器来防止级联错误。

负载平衡和服务发现开销增加

参与服务的冗余和可用性需求可以通过在负载平衡器后面进行设置来解决。 这增加了每个服务的间接级别。 此外,每个服务都需要参与中央服务发现设置。 这使它可以推送自己的地址并解析下游服务的地址。

耦合

同步系统在一段时间内会表现出更紧密的耦合。 服务之间没有抽象,便直接绑定到其他服务的契约。 这会在一段时间内形成强耦合。 对于合同中的简单更改,所有权服务必须尽早采用版本控制。 从而增加了系统复杂度。 或者,它使与合同相关的所有消费者服务的变更都顺势而为。

使用诸如服务网格之类的新兴体系结构范例,可以解决某些陈述的问题。 Istio,Linkerd,Envoy等工具可用于创建服务网格。 这个空间正在成熟并且仍然很有希望。 它可以帮助构建同步,解耦和容错的系统。

异步

异步通信非常适合于分布式体系结构。 它消除了等待响应的需要,从而使两个或多个服务的执行脱钩。 异步通信的实现有几种变体。 通过RPC(例如grpc)或通过中介消息总线直接调用远程服务的例子很少。 协调的消息传递和事件编排都使用消息总线作为通道。

中央消息总线的优点之一是一致的通信和消息传递语义。 与服务之间的直接异步通信相比,这可能是一个巨大的优势。 通常使用诸如消息总线之类的介质来促进跨服务的一致通信。 下面讨论的异步通信的变体将采用中央消息管道

变化

异步通信可以更好地处理零星的流量。 体系结构中的每个服务要么生成消息,要么消费消息,或者两者都做。 让我们看看这种范例的不同结构风格。

编排的异步事件

在这种方法中,每个组件都侦听中央消息总线并等待事件。 事件的到来是执行的信号。 执行所需的任何上下文都是事件有效负载的一部分。 触发下游事件是每个服务拥有的责任。 基于事件的体系结构的目标之一是分离组件。 不幸的是,设计需要负责以满足这种需求。

通知组件可能期望事件触发电子邮件或SMS。 由于其他服务所需要做的就是生成事件,因此看起来似乎是分离的。 但是,确实需要有人来决定通知和内容的类型。 两种通知都可以根据传入的事件信息做出该决定。 如果发生这种情况,那么我们已经在通知和上游服务之间建立了联系。 如果上游服务将此作为有效负载的一部分包括在内,则它们仍会知道下游的流量。

即使这样,事件编排也非常适合需要发生的隐式动作。 错误处理,通知,搜索索引等

它遵循分散的工作流程管理。 该体系结构可很好地用于大量写入的系统。 缺点是同步读取需要中介,并且工作流会分散在整个系统中。

编排,异步和顺序

我们可以从协调的同步通信中借鉴一些方法。我们可以与中心的协调器建立异步通信。

每个服务都是中央消息总线的生产者和消费者。协调器的职责涉及将消息路由到其相应的服务。每个组件都使用传入的事件或消息,并在消息队列上返回响应。 Orchestrator使用此响应并进行转换,然后再路由到下一步。该循环一直持续到指定的工作流达到系统中的最后状态为止。

通过这种样式,工作流程管理对于协调器是本地的。该系统适用于大量写入流量。同步消费者必须进行调解。这是所有异步变体中普遍存在的东西。

在编排的系统中,舞蹈编排耦合问题的解决方案更为优雅。在这种情况下,工作流程与Orchestrator一起使用。丰富的工作流程规范可以捕获诸如通知类型和内容模板之类的信息。工作流程的任何更改都将保留在Orchestrator服务中。

 

 

与编排和事件编排混合

另一个成功的变体是同时具有编排和事件编排的混合系统。 编排非常适合显式流程执行,而编排可以处理隐式执行。 工作流中叶节点的执行可以是隐式的。 工作流规范可以促进特定步骤中事件的发出。 这可能导致执行诸如通知,索引编制等任务。 编排可以继续推动显式执行。

两种方法的这种融合提供了两全其美的方法。 虽然,但仍需要采取预防措施,以确保他们不会重叠职责,明确界限决定其职能。

总览

异步体系结构样式解决了同步系统具有的一些陷阱。 异步设置在临时请求的情况下效果更好。 中央队列允许服务赶上合理的请求积压。 当许多请求在短时间内到达时或服务暂时中断时,这很有用。

每个服务都作为使用者或生产者连接到消息队列。 仅消息队列需要服务发现。 因此,对中央服务发现解决方案的需求减少了。 另外,由于服务的多个实例连接到队列,因此不需要外部负载平衡。 这样可以避免负载均衡器引入的另一种间接级别。 它还允许服务无缝地线性扩展。

权衡取舍

本质上是异步的服务流可能很难通过系统。 采用异步通信的系统需要进行一些折衷。 让我们来看一些。

更高的系统复杂度

异步系统往往比同步系统复杂得多。 但是,系统的复杂性以及对性能和规模的要求对于开销是合理的。 一旦被采用,协调器和单个组件都需要包含异步执行。

/查询需要中介

除非专门处理,否则同步使用者将受异步体系结构的最大影响。 使用者需要适应与异步系统一起工作,或者系统应该为使用者提供一个同步接口。

异步体系结构很适合写繁重的系统。 但是,它需要中介才能进行同步读取/查询。 有几种方法可以满足这种需求。 每个人都有一定的复杂性。

同步包装器

所有方法中最简单的方法是在异步系统上构建同步包装器。 这是可以调用下游异步流的入口点。 同时,它保持请求等待,直到响应返回或发生超时。 同步包装器是有状态的组件。 传入请求将其自身与其所连接的服务器绑定在一起。 来自下游服务的响应需要到达原始请求正在等待的服务器。 对于分布式系统,尤其是大规模运行的系统,这不是理想的选择。 但是,它很容易编写且易于管理。 对于具有合理缩放和性能需求的系统,它可以满足要求。 在进行更激烈的重组之前,应该考虑使用同步包装器。

CQRS

CQRS是一种将读取与写入分开的体系结构样式。 CQRS给系统带来了大量的风险和复杂性。 非常适合大规模运行且需要大量读写操作的系统。 在CQRS体系结构中,数据从写入数据库流到读取数据库。 查询在经过读取优化的数据库上运行。 读/写层是分开的,并且系统最终保持一致。 这两层的优化是独立的。 这样的系统结构复杂得多,但扩展性更好。 此外,组件可以保持无状态(与同步包装器不同)。

 

双重支持

在同步包装程序和CQRS实现之间有中间立场。 每个服务/组件都可以支持同步查询和异步写入。 这对于中等规模的系统非常有效。 因此,读取查询可以在组件之间跳转,以同步完成读取。 另一方面,写入系统将沿异步通道流动。 但是,这里需要权衡。 不可能同时针对读写进行系统优化。 这对于在高流量下运行的系统是有益的。

消息总线是故障的中心点

这不是权衡取舍,而是预防措施。 在异步通信方式中,消息总线是系统的骨干。 所有服务不断从消息总线产生和消耗消息。 这使消息总线成为系统的致命弱点,因为它仍然是故障的中心。 消息总线支持水平缩放非常重要,否则它可能会违反分布式系统的目标。

最终一致性

异步系统最终可能是一致的。 这意味着即使系统已发出写操作,查询结果也可能不是最新的。 尽管这种权衡取舍可以使系统更好地扩展,但还是要考虑系统的设计和用户体验两者。

混合

可以同时使用异步和同步通信。 完成后,这两种方法之间的权衡将抵消其优势。 系统必须交替处理两种通信方式。 同步调用可以级联降级和故障。 另一方面,异步通信将增加设计的复杂性。 以我的经验,隔离地选择一种方法对于系统设计会更有成果。

判决

马丁·福勒(Martin Fowler)有一个很棒的博客,介绍了构建微服务的决策。 一旦确定,微服务架构就需要仔细考虑其执行流程样式。 对于写入而言,重型系统异步是使用异步同步包装器的最佳选择。 而对于繁重的系统,同步通信效果很好。

对于读写繁重但规模要求适中的系统,同步设计在使设计保持简单方面将大有帮助。 如果系统具有很大的规模和性能需求,那么采用CQRS模式的异步设计可能是可行的方法。

 

> 喜欢这篇文章的可以点个赞,欢迎大家留言评论,记得关注我,每天持续更新技术干货、职场趣事、海量面试资料等等
 > 如果你对java技术很感兴趣也可以交流学习,共同学习进步。 
> 不要再用"没有时间“来掩饰自己思想上的懒惰!趁年轻,使劲拼,给未来的自己一个交代

文章写道这里,欢迎完善交流。最后奉上近期整理出来的一套完整的java架构思维导图,分享给大家对照知识点参考学习。有更多JVM、Mysql、Tomcat、Spring Boot、Spring Cloud、Zookeeper、Kafka、RabbitMQ、RockerMQ、Redis、ELK、Git等Java干货

本文转载自博客园,原文链接:https://www.cnblogs.com/youruike1/p/12190804.html

全部评论: 0

    我有话说: