0
点赞
收藏
分享

微信扫一扫

《微服务架构设计模式》第三章 微服务架构中的进程间通信


内容总结自《微服务架构设计模式》


微服务架构中的进程间通信

  • 一、通信概述
  • 通信方式
  • API定义
  • 消息格式
  • 二、同步通信
  • REST
  • gRPC
  • 断路器
  • 服务发现
  • 三、异步通信
  • 消息
  • 消息通道
  • 消息代理
  • 消息问题



)



一、通信概述

通信方式

有很多进程间通信技术可供开发者选择。服务可以使用基于同步请求/响应的通信机制,例如HTTP REST或gRPC。另外,也可以使用异步的基于消息的通信机制,比如AMQP或STOMP。消息的格式也不尽相同。服务可以使用具备可读性的格式,比如基于文本的JSON或XML。也可以使用更加高效的、基于二进制的Avro或Protocol Buffers 格式。

客户端和服务端的交互方式可以分为两个不同的维度
维度一:一对一、一对多
维度二:同步模式、异步模式

一对一

一对多

同步模式

请求/响应


异步模式

异步请求/响应

单向通知

发布/订阅

发布/异步响应


API定义

相比于单体架构,我们面临的挑战在于:并没有一个简单的编程语言结构可以用来构造和定义服务的API。根据定义,服务和它的客户端并不会一起变一。如果使用不兼容的API部署新版本的服务,虽然在编译阶段不会出现错误,但是会在运行时故障。



API需要优先设计

即使在那些最简单的项目中,组件和API之间也经常发生冲突。例如,负责后端的Java程序员和负责前端的AngularJS程序员都声称完成了开发,然而这个应用程序却无法工作。前端的REST和WebSocket API无法与后端的API一起工作。最终导致这个应用程序的前端和后端无法正常通信!

在现代应用程序中,对API有着极高的可用性要求,一般会采用滚动升级的方式来更新服务,因此一个服务的旧版本和新版本肯定会共存。所以在处理API的时候存在相关的措施:

  1. 语义化的版本控制:规范化如何使用版本号,正确的方式递增版本号
  2. 进行次要并且向后兼容的改变:添加可选属性、向响应添加属性、添加新操作
  3. 进行主要并且不向后兼容的改变:服务强制客户端升级,必须同时支持新老版本API


消息格式

消息的格式可以分为两大类:文本(JSON、XML等)和二进制(Protocol Buffers、Avro等)


二、同步通信

《微服务架构设计模式》第三章 微服务架构中的进程间通信_架构



REST

REST是一种(总是)使用HTTP协议的进程间通信机制。REST提供了一系列架构约束,当座位整体使用时,它强调组件交互的可扩展性、接口的通用性、组件的独立部署,以及那些能减少交互延迟的中间价,它强化了安全性,也能封装遗留系统。

REST中的一个关键概念是资源,它通常表示单个业务对象,例如客户或产品,或业务对象的集合。REST使用HTTP动词来操作资源,使用URL饮用这些资源。

好处:

  1. 它非常简单,并且大家都很熟悉
  2. 可以使用浏览器扩展(比如Postman插件)或者curl之类的命令行(假设使用的是JSON或其他文本格式)来测试HTTP API
  3. 直接支持请求/响应方式的通信
  4. HTTP对防火墙友好
  5. 不需要中间代理,简化系统架构

弊端:

  1. 它只支持请求/响应方式的通信
  2. 可能导致可用性降低。由于客户端和服务直接通信而没有代理来缓冲消息,因此他们必须在REST API调用期间都保持在线
  3. 客户端必须知道实例的位置(URL),这是现在应用程序中的一个重要问题。客户端必须使用所谓的服务发现机制来定位服务实例
  4. 在单个请求中获取多个资源具有挑战性
  5. 有时很难将多个更新操作映射到HTTP动词


gRPC

gRPC是REST的另一种替代方案,这是一个用于编写跨语言客户端和服务端的框架。gRPC使用Protocol Buffers是一种高效且紧凑的二进制格式。他是一种标记格式。

好处:

  • 设计具有复杂更新操作的API非常简单。
  • 它具有高效、紧凑的进程间通信机制,尤其是在交换大量消息时。支持在远程过程调用和消息传递过程中使用双向流式消息方式。
  • 它实现了客户端和用各种语言编写的服务端之间的互操作性。

弊端:

  • 与基于REST/JSON的API机制相比,JavaScript客户端使用基于gRPC的API需要 做更多的工作。
  • 旧式防火墙可能不支持HTTP/2。

gRPC是REST的一个引人注目的替代品,但与REST一样,它是一种同步通信机制,因此它也存在局部故障的问题。



断路器

本质就是微服务中提到的服务熔断和降级

当一个服务同步调用另一个服务时,它应该使用Netflix描述的方法来保护自己,这种方法包括以下机制的组合

  • 网络超时
  • 限制客户端向服务器发送请求的数量:限流
  • 断路器模式:控制客户端发出请求的成功和失败数量


服务发现

实现服务发现有以下两种主要方式:服务及其客户直接与服务注册表交互、通过部署基础设置来处理服务发现

1、服务及其客户直接与服务注册表交互

服务实例使用服务注册表注册其网络位置

  1. 自注册:服务实例向服务注册表注册自己
  2. 客户端发现:客户端从服务表检索可用服务实例的列表,并在他们之间进行负载平衡

《微服务架构设计模式》第三章 微服务架构中的进程间通信_java_02

二、通过部署基础设置来处理服务发现

部署平台(Docker、K8S)为每个服务提供DNS名称、虚拟IP(VIP)地址和解析为VIP地址的DNS名称。

  1. 第三方注册:服务实例由第三方自动注册到服务注册表
  2. 服务端发现:客户端向路由器发出请求,路由器负责服务发现

《微服务架构设计模式》第三章 微服务架构中的进程间通信_java_03


三、异步通信

使用消息机制时,服务之间的通信采用异步交换消息的方式完成。

消息模型的定义:消息通过消息通道进行交换,发送方(应用程序或服务)将消息写入通道接收方(应用程序或服务)从通道读取消息



消息

消息由消息头部和主体组成。标题是名称和值对集合,描述正在发送的数据和元数据。除了消息发送提供的名称和值对外,消息头部还包含其他信息,例如发件人或消息传递基础设施生成的唯一消息ID,以及可选的返回地址,该地址制定发送回复的消息通道。消息正文是以文本或二进制格式发送的数据。

消息有以下几种类型:

  1. 文档:仅包含数据的通信消息
  2. 命令:一条等同于RPC请求的消息
  3. 事件:表示发送方这一端发生了重要的时间,事件通常是领域事件,表示领域对象的状态发生的更改


消息通道

《微服务架构设计模式》第三章 微服务架构中的进程间通信_java_04

有两种消息通道:

  1. 点对点通道(一对一)
  2. 发布-订阅通道(一对多)


消息代理

类比理解为具体的MQ产品(MetaQ、Kafuka等)

《微服务架构设计模式》第三章 微服务架构中的进程间通信_客户端_05



消息问题

处理并发和消息顺序

常见的解决方案是使用分片(分区)通道:

  1. 分片通道由两个或多个分片组成,每个分片的行为类似于一个通道
  2. 发送方在消息头部指定分片键,通常是任意字符串或字节序列。消息代理使用分片键将消息分配给特定的分片
  3. 消息代理将接受方的多个实例组合在一起,并将它们视为相同的逻辑接受方

《微服务架构设计模式》第三章 微服务架构中的进程间通信_微服务_06

处理重复消息

由于保证有且仅有一次的消息传递通常成本很高,所以大多数消息代理承诺至少成功传递一次消息

解决重复消息常见做法:

  1. 编写幂等消息处理程序
  2. 跟踪消息并丢弃重复项

处理事务消息

常见做法是使用数据库表作为消息队列(借助本地的ACID事务),将需要发送的消息,存储到数据库中。

将消息从数据库移动到消息代理并对外发布有两种不同方法:

  1. 通过轮询模式发布事件:定时轮询select表的数据
  2. 使用事物日志拖尾模式发布事件:监听数据库的日志文件


举报

相关推荐

0 条评论