「第二部:容器和微服务架构](11) 微服务架构中的通信

简介: 「第二部:容器和微服务架构](11) 微服务架构中的通信

在单个进程上运行的单片应用程序中,组件使用语言级方法或函数调用彼此调用。如果使用代码创建对象(例如,new ClassName()),则可以强耦合这些对象;如果使用依赖注入,则可以通过引用抽象而不是具体的对象实例,以分离的方式调用这些对象。不管怎样,对象都在同一进程中运行。当从单一应用程序转变为基于微服务的应用程序时,最大的挑战在于改变通信机制。从进程内方法调用到服务的RPC调用的直接转换将导致在分布式环境中性能不佳的聊天和不高效的通信。正确设计分布式系统的挑战是众所周知的,甚至还有一个被称为分布式计算谬误的经典,它列出了开发人员在从单一设计转向分布式设计时经常做出的假设。


没有一个解决方案,只有几个。一种解决方案是尽可能地隔离业务微服务。然后在内部微服务之间使用异步通信,并用粗粒度通信替换对象之间的进程内通信中的典型细粒度通信。您可以通过对调用进行分组并将聚合多个内部调用结果的数据返回给客户端来完成此操作。


基于微服务的应用程序是在多个进程或服务上运行的分布式系统,通常甚至跨多个服务器或主机运行。每个服务实例通常是一个流程。因此,服务必须使用进程间通信协议(如HTTP、AMQP)或二进制协议(如TCP)进行交互,具体取决于每个服务的性质。


微服务社区提倡“智能端点和哑管道”的理念这一口号鼓励设计尽可能在微服务之间分离,并在单个微服务中尽可能具有凝聚力。如前所述,每个微服务都拥有自己的数据和域逻辑。但是,组成端到端应用程序的微服务通常只是通过使用REST通信而不是复杂的协议(如WS-*和灵活的事件驱动通信)进行编排,而不是使用集中的业务流程编排器。


这两种常用的协议是HTTP请求/响应和资源api(在大多数情况下查询时),以及在跨多个微服务通信更新时的轻量级异步消息传递。以下各节将更详细地解释这些问题。


通信类型


客户机和服务可以通过多种不同类型的通信进行通信,每种通信都针对不同的场景和目标。最初,这些类型的通信可以分为两个轴。


第一个轴定义协议是同步的还是异步的:

  • 同步协议。HTTP是一种同步协议。客户端发送请求并等待服务的响应。这与客户端代码执行无关,客户端代码执行可以是同步的(线程被阻塞)或异步的(线程不被阻塞,响应最终将到达回调)。这里重要的一点是,协议(HTTP/HTTPS)是同步的,客户端代码只有在接收到HTTP服务器响应时才能继续其任务。
  • 异步协议。其他协议如AMQP(许多操作系统和云环境支持的协议)使用异步消息。客户端代码或消息发送者通常不会等待响应。它只是在向RabbitMQ队列或任何其他消息代理发送消息时发送消息。

第二轴定义通信是否有一个或多个接收器:

  • 单接收器。每个请求必须由一个接收者或服务处理。这种通信的一个例子是命令模式。
  • 多个接收器。每个请求都可以由零到多个接收器处理。这种类型的通信必须是异步的。例如,在事件驱动架构等模式中使用的发布/订阅机制。当通过事件在多个微服务之间传播数据更新时,这基于事件总线接口或消息代理;通常通过服务总线或类似的工件(如Azure服务总线)通过使用主题和订阅来实现。

基于微服务的应用程序通常会使用这些通信样式的组合。最常见的类型是在调用常规Web API HTTP服务时使用HTTP/HTTPS之类的同步协议进行单接收器通信。微服务通常也使用消息传递协议在微服务之间进行异步通信。

这些轴是很好知道,所以你有可能的沟通机制,但他们不是重要的关注时,建设微服务。在集成微服务时,客户端线程执行的异步性和所选协议的异步性都不是重点。重要的是能够异步集成您的微服务,同时保持微服务的独立性,如下一节所述。


异步微服务集成增强了微服务的自主性


如前所述,构建基于微服务的应用程序时,重要的一点是集成微服务的方式。理想情况下,您应该尽量减少内部微服务之间的通信。微服务之间的通信越少越好。但在很多情况下,您必须以某种方式集成微服务。当您需要这样做时,这里的关键规则是微服务之间的通信应该是异步的。这并不意味着您必须使用特定的协议(例如,异步消息传递与同步HTTP)。这只是意味着微服务之间的通信应该只通过异步传播数据来完成,但不要依赖于其他内部微服务作为初始服务HTTP请求/响应操作的一部分。


如果可能,永远不要依赖多个微服务之间的同步通信(请求/响应),即使是查询。每个微服务的目标都是自治的,并可供客户机消费者使用,即使作为端到端应用程序一部分的其他服务已关闭或不正常。如果您认为需要从一个微服务调用其他微服务(如执行数据查询的HTTP请求)才能向客户端应用程序提供响应,那么您的体系结构在某些微服务失败时将无法恢复。

此外,如图4-15的第一部分所示,在微服务之间具有HTTP依赖关系(如使用HTTP请求链创建长请求/响应周期时),不仅使微服务不具有自治性,而且一旦该链中的某个服务性能不好,它们的性能就会受到影响。

在微服务(如查询请求)之间添加的同步依赖项越多,客户端应用程序的总体响应时间就越差。


图15 微服务间通信中的反模式和模式


如上图所示,在同步通信中,在为客户机请求提供服务的同时,在微服务之间创建请求的“链”。这是一种反模式。在异步通信中,微服务使用异步消息或http轮询来与其他微服务通信,但客户机请求会立即得到服务。


如果您的微服务需要在另一个微服务中引发附加操作,请尽可能不要同步执行该操作,并将其作为原始微服务请求和回复操作的一部分。相反,要异步进行(使用异步消息传递或集成事件、队列等)。但是,尽可能不要作为原始同步请求和应答操作的一部分同步调用操作。


最后(这是构建微服务时出现的大多数问题),如果初始微服务需要最初由其他微服务拥有的数据,不要依赖于对该数据进行同步请求。相反,通过使用最终一致性(通常是通过使用集成事件,如后面几节所述)将数据(仅需要属性)复制或传播到初始服务的数据库中。


正如前面在识别每个微服务部分的域模型边界中所指出的,在多个微服务之间复制某些数据并不是一个错误的设计相反,这样做时,您可以将数据转换为该附加域或有界上下文的特定语言或术语。例如,在eShopOnContainers应用程序中,有一个名为identity api的微服务,它负责用户的大部分数据,实体名为user。但是,当需要在Ordering microservice中存储有关用户的数据时,可以将其存储为名为Buyer的不同实体。买方实体与原始用户实体共享相同的标识,但它可能只有订购域所需的少数属性,而不是整个用户配置文件。

您可以使用任何协议在微服务之间异步通信和传播数据,以便最终保持一致性。如前所述,可以使用事件总线或消息代理来使用集成事件,甚至可以通过轮询其他服务来使用HTTP。没关系。重要的规则是不要在微服务之间创建同步依赖关系。


以下各节介绍了在基于微服务的应用程序中可以考虑使用的多种通信样式。

通信风格


根据要使用的通信类型,可以使用许多协议和选项进行通信。如果使用的是基于同步请求/响应的通信机制,那么HTTP和REST方法等协议是最常见的,尤其是在Docker主机或微服务集群之外发布服务时。如果您在服务之间进行内部通信(在Docker主机或微服务集群内),您可能还需要使用二进制格式的通信机制(如使用TCP和二进制格式的WCF)。或者,可以使用异步的、基于消息的通信机制,如AMQP。


还有多种消息格式,如JSON或XML,甚至是二进制格式,这样可以更高效。如果您选择的二进制格式不是标准格式,那么使用该格式公开发布您的服务可能不是一个好主意。您可以使用非标准格式在微服务之间进行内部通信。在Docker主机或微服务群集(例如Docker orchestrators)内的微服务之间通信时,或者在与微服务对话的专用客户端应用程序之间通信时,可以这样做。


基于HTTP和REST的请求/响应通信


当客户机使用请求/响应通信时,它向服务发送一个请求,然后服务处理该请求并发回一个响应。请求/响应通信特别适合于从客户端应用程序查询实时UI(实时用户界面)的数据。因此,在微服务架构中,您可能会对大多数查询使用这种通信机制,如图4-16所示。


图16 使用HTTP请求/响应通信(同步或异步)


当客户机使用请求/响应通信时,它假设响应将在短时间内到达,通常不到一秒,或最多几秒。对于延迟响应,您需要实现基于消息模式和消息技术的异步通信,这是我们在下一节中解释的另一种方法。


请求/响应通信的流行体系结构样式是REST。这种方法基于HTTP协议,并与之紧密耦合,包括GET、POST和PUT等HTTP动词。REST是创建服务时最常用的架构通信方法。在开发ASP.NET核心Web API服务时,可以实现REST服务。


当使用HTTP REST服务作为接口定义语言时,还有额外的价值。例如,如果使用夸张的元数据来描述服务API,则可以使用生成客户端存根的工具来直接发现和使用服务。


额外资源


  • Martin Fowler. Richardson Maturity Model A description of the REST model.
    https://martinfowler.com/articles/richardsonMaturityModel.html
  • Swagger The official site.
    https://swagger.io/
  • 基于HTTP的推送与实时通信
  • 另一种可能性(通常用于与REST不同的目的)是与更高级别的框架(如ASP.NET signaler)和协议(如WebSockets)进行实时的一对多通信。
  • 如图4-17所示,实时HTTP通信意味着您可以让服务器代码在数据可用时将内容推送到连接的客户端,而不是让服务器等待客户端请求新数据。

  • 图17 一对一实时异步消息通信
  • signaler是实现从后端服务器将内容推送到客户端的实时通信的好方法。由于通信是实时的,客户端应用程序几乎可以立即显示变化。这通常由WebSockets等协议处理,使用许多WebSockets连接(每个客户端一个)。一个典型的例子是,当一个服务同时向许多客户端web应用程序传递一个体育游戏的分数变化时。
相关文章
|
1天前
|
缓存 监控 负载均衡
探索微服务架构中的API网关模式
在现代软件开发领域,微服务架构因其灵活性和可扩展性而备受青睐。本文将深入探讨微服务架构中至关重要的组件——API网关。通过分析API网关的核心功能、设计原则以及实际应用案例,我们旨在揭示其在提高系统性能、增强安全性及简化客户端与服务间通信中的重要作用。结合最新研究和实际开发经验,本文将为读者提供关于如何有效实施API网关的深刻见解。
|
1天前
|
存储 负载均衡 云计算
微服务架构中的服务发现与注册机制
在分布式系统设计中,微服务架构因其灵活性和可伸缩性而受到青睐。本文深入探讨了微服务架构下的服务发现与注册机制,通过分析Eureka、Consul和Zookeeper等工具的原理与实践,揭示了这些机制如何优化服务间的通信和故障转移。文章结合最新研究和案例,提供了对微服务架构中关键组件的深刻见解,并讨论了其在不同场景下的应用效果。
|
1天前
|
Kubernetes Java 测试技术
探索微服务架构的演变与实践
【6月更文挑战第28天】在数字化时代,软件架构不断演进以应对复杂多变的业务需求。本文将深入探讨微服务架构从概念到实践的发展过程,分析其设计原则、技术选型及实施策略,并结合作者亲身经验,阐述在微服务转型过程中的挑战与解决之道。
|
1天前
|
Kubernetes Cloud Native Serverless
云原生时代的微服务架构演进之路
【6月更文挑战第28天】在数字化转型的大潮中,企业不断寻求更高效、灵活的软件开发与部署方式。云原生技术因此应运而生,它不仅改变了应用的开发模式,也重塑了微服务架构的未来。本文将探讨云原生环境下微服务架构的演进路径,包括容器化、服务网格、无服务器计算等关键技术的应用与挑战,并展望未来微服务架构的发展方向。
|
2天前
|
负载均衡 Java API
使用Spring Cloud构建Java微服务架构
使用Spring Cloud构建Java微服务架构
|
2天前
|
运维 Kubernetes 云计算
云计算时代的运维革新:容器化与微服务架构的融合之道
在云计算技术飞速发展的当下,企业IT运维面临前所未有的挑战与机遇。传统的运维模式已难以满足现代业务对敏捷性、可伸缩性和自动化的需求。本文深入探讨了容器化技术和微服务架构如何共同推动运维领域的革命,通过数据支持和科学分析,揭示了这一融合趋势如何提高运维效率、降低风险并促进创新。
|
1天前
|
Cloud Native 安全 开发者
云原生架构的演进与实践:从微服务到无服务器计算
本文深入探讨了云原生技术的最新进展,特别关注微服务和无服务器计算模型。通过分析相关研究数据和行业案例,文章揭示了云原生架构如何推动现代应用开发,提升运维效率,并实现资源的最优化配置。文中详细讨论了云原生生态系统中的关键组成部分,包括容器化、自动化管理工具和服务网格,以及它们如何共同促进敏捷性和可扩展性。此外,文章还分析了云原生安全策略的重要性,以及如何在保障安全的同时,保持系统的灵活性和高效性。
|
1天前
|
Kubernetes Cloud Native Docker
云原生技术演进之路:从微服务到容器化
在数字化浪潮的推动下,云原生技术不断演进,为现代软件开发带来革命性变化。本文将深入探讨云原生技术的核心要素—微服务和容器化,揭示它们如何促进软件的快速迭代、可扩展性和可靠性提升。通过分析相关数据和案例研究,我们旨在阐明云原生技术在加速企业数字化转型中的关键作用。
|
1天前
|
缓存 安全 API
深入理解微服务架构中的API网关模式
本文将探讨API网关在微服务架构中的核心作用和设计考量,通过分析相关研究与实践案例,揭示其在系统性能优化、安全增强及简化客户端交互方面的关键价值。我们将基于最新的行业报告和学术文献,结合具体的使用场景,对API网关的实现策略进行深度剖析,旨在为读者提供一套系统的理解和应用API网关的知识框架。
|
1天前
|
运维 监控 负载均衡
云原生架构下的微服务治理实践
【6月更文挑战第28天】在数字化转型的浪潮中,云原生技术以其高效、灵活的特性成为企业IT架构升级的首选。本文将深入探讨在云原生环境下,如何通过微服务治理提升系统的可维护性、可扩展性和韧性。我们将从服务发现与注册、配置管理、服务监控、路由与负载均衡、以及故障处理等方面出发,结合具体案例,为读者提供一套完整的微服务治理策略,旨在帮助开发和运维团队更好地管理和优化他们的云原生应用。