简介
在单体应用中,各模块间是直接通过编程语言调用函数来直接调用的。但在微服务这种分布式应用中,每个服务实例都是一个进程,因此服务间的交互必须通过 进程间通信(IPC)来实现。
交互模式(通信方式)
当为一个服务选择 IPC 时,首先要考虑如何交互,交互方式有很多种。从两个维度归类如下。
以通信方个数分类:
- 一对一:每个客户端请求一个服务实例
- 一对多:每个客户端请求多个服务实例
以同步异步来服:
- 同步模式:即阻塞等待响应
- 异步模式:即非阻塞
由此,取迪卡尔集,有以下几种方式
- 一对一时
- 请求/响应,即阻塞方式调用
- 通知,即单向请求,只管发送,还管响应
- 请求/异步响应,即请求之后客户端不会阻塞,响应什么时候来了什么时候处理
- 一对多时
- 通过发布/订阅模式:客户端发布了消息,订阅者对消息进行消费
- 发布/异步响应模式:客户端发布了消息,订阅者什么时候返回什么时候处理
通常在一个微服务系统中,并不是单一的一个通信机制,而是有多种的组合。
具体的通信(API)
具体使用哪种通信方式(或者说 IPC),就体现在 API 的定义上。如使用消息机制,则由消息频道(channel)和消息类型构成;使用 HTTP 机制,API 则由 URL 和请求体、响应格式构成。
API 的变化
在单体应用中,由于前后端比较统一,所以只需更新调用 URL 并同步调用者改变调用即可。但对于基于微服务架构来说,这很困难。因为可能有多方客户端在使用。
在微服务架构中,如何处理 API 的变化,这有赖于变化有多大。如果只是微小的变化,和以往版本兼容,如增加字段,就可以直接修改;但若改动较大,就需要考虑 URL 版本升级,如 HTTP 中在 URL 上加上版本号。同时,服务需要兼容不同版本请求的处理,或者将不同版本的请求分配到不同的服务中。
处理 API 失败
IPC 通信中,为了防止通信失败而导致占用资源(如线程占用),所以必须加超时机制。所以一般处理 API 的措施有包括:
- 网络超时。当等待响应时,不可无限期阻塞,使用超时机制及时释放资源
- 限制请求次数。可以对某特定的请求设置一个访问上限,如果超过一个上限,再有请求到来时,终止请求
- 断路器模式(Circuit Breaker Pattern)。记录失败请求数量及比例,当失败率超过阈值,触发断路器断开一断时间。
- 提供回滚。
IPC 技术
IPC 技术有许多种:
如同步的有 HTTP 的 REST 或 Thrift;
异步的基于消息的有 AMQP 或 STOMP。
除此之外还有消息格式供选择:
如 JSON 或 XML,它们都是可读的、基于文本的消息格式;
另外还有基于二进制的格式(效率更高),如 Avro 和 Protobuf。
异步通信技术
基于消息
一个消息由 头部 和 消息体 构成。消息通过 channel 发送,任何数据量的生产者都可以发送消息到 channel,同样,任何消费者都可以从 channnel 中取数据。
channel 又分两类,一类是 点对点,一类是 发布/订阅。
点对点模式实现了一对一的交互;而发布/订阅则可以实现一对多的交互。
基于消息的好处
- 解耦客户端和服务器。
- 异步。也就是说请求无须等待响应,只要我发了就行,因为最终一定会被处理掉
- xxx
基于消息的缺点
- 引入了消息系统这一层,那就要考虑安装、配置、部署、高可用等
- 请求响应的复杂性
同步通信技术
最常用的是 REST 和 Thrift。
REST
是一种很流行的 RESTful 风格的 API。它的一个重要概念就是 REST 是一个资源,一般代表一个业务对象,将对此资源的请求表现在 URL 上。
xxx
Thrift
xxx
消息格式
消息格式一般分为两类,文本和二进制格式。
文本有 JSON 和 XML,它们可读,且自描述的。使用者可以从中选取自己需要的字段进行使用。
文本消息的缺点主要就是大,因为便于描述,所以包含了一些方便人们阅读的信息。因此,你可能需要考虑二进制格式。
二进制格式有 Protocol Buffer 和 Apache Avro。它们的不同在于 Protobuf 使用的是加标记(tag)的字段,而 Avro 的接收者需要知道 Schema 来解析消息。因此 Protobuf 更容易演进。
总结
本章讲述了进程间通信的几种方式。你需要考虑有几个问题:
- 如何挑选 API 机制
- 如何交互
- 如何标识API
- API如何升级
- 如何处理部分失败
网友评论