昨天我们一起学习的微服务数据模式,今天我们来学习一下微服务的通信设计模式,通信是保证服务请求核心要素,选择合适的一个通信协议对系统来说可以达到事半功倍。
目前各种微服务通信社区上,很多种支持RPC模式。有同步请求/响应通信机制,例如基于 HTTP 的 REST 或 GraphQL,或 gRPC。或者可以使用异步的、基于消息的通信机制,例如 AMQP(高级消息队列协议)或 STOMP(简单/流式面向文本的消息传递协议)。此外,还有许多不同的消息格式。这些格式可以是可读的,例如 JSON 和 XML。他们还可以使用更高效的二进制格式,例如 Avro 或 Protobuf。
在选择 RPC 机制之前,考虑一下服务与其客户端之间的交互方式是很有必要的。客户服务交互有两个维度。
RPC 本质上是一种消息交换。其中一个重要的设计是消息包含数据的格式。消息格式的选择会影响 RPC 的效率、API 的可用性及其可演化性。
消息格式有两种主要类型:文本和二进制。
JSON 和 XML 是最流行的基于文本的格式。
基于文本的消息格式的优点
基于文本的消息格式的缺点
Thrift、Protocol Buffers (Protobuf) 和 Avro 是最流行的二进制格式。
二进制消息格式的优点
二进制消息格式的缺点
当客户端请求服务时,服务会处理请求并发回响应。虽然一些客户端可能会在等待响应时阻塞,但其他客户端可能具有反应性、非阻塞架构。
代理接口通常封装底层通信协议。
有多种通信协议可供选择,例如 REST、gRPC 和 GraphQL 等。
REST 基于资源的概念,它表示单个业务对象。HTTP(超文本传输协议)用于实现 REST。REST 使用 HTTP 来操作由 URL 引用的资源。
API 必须使用 IDL(接口定义语言)定义。最流行的 REST IDL 之一是开放 API 规范,它是从Swagger开源项目演变而来的。
由于 REST API 通常基于业务对象,因此在一个请求中请求多个相关对象是设计 REST API 时的常见难题之一。客户端必须至少对相关对象发出多次请求。
使用查询参数,API 可以使客户端在获取资源时检索相关资源。由于这种方法缺乏可扩展性,GraphQL和Netflix Falcor等替代 API 技术变得越来越受欢迎。
另一个常见的 REST API 设计问题是将要对业务对象执行的操作映射到 HTTP 请求上。REST API 使用 PUT 来更新,但是有多种方法可以操作订单,包括取消订单、修改订单等。一种解决方案是定义一个子资源,如 /orders/{orderId}/cancel 或 /orders/{orderId}/revise 以更新资源的特定方面或在 URL 查询参数中指定动词。但这些解决方案并不是真正的 RESTful。
由于这个问题,REST 的替代品(例如gRPC)越来越受欢迎。
由于 HTTP 仅提供一组有限的请求方式,因此设计支持多个更新操作的 REST API 可能具有挑战性。
谷歌推出的跨语言客户端和服务器的框架 gRPC 可以解决这个问题。使用基于协议缓冲区的 IDL 定义 gRPC API,这是 Google 用于序列化结构化数据的语言设计机制。是一种同步通信机制。使用 HTTP/2,客户端和服务器以协议缓冲区格式交换二进制消息。
GraphQL 解决了使用单个请求获取多个资源的问题。GraphQL 主要用于从客户端应用程序查询数据库。在后端,GraphQL 向 API 指定如何将数据呈现给客户端。GraphQL 重新定义了开发人员使用 API 的方式,提供更大的灵活性和更快的上线速度;改进了客户端-服务器交互,使前者能够进行精确的数据请求,并只获得他们需要的数据。
GraphQL 服务器为客户端提供模式:可以请求的数据模型。
使用消息传递时,服务会异步交换消息。基于消息的应用程序通常使用像 RabbitMQ 这样的消息代理,充当服务之间的中介。服务客户端通过向服务发送消息来向服务发出请求。如果期望响应,服务实例将向客户端发送单独的消息。由于通信是异步的,客户端不会等待响应。相反,客户端是假设不会立即收到响应的。
异步消息传递使实现单向通知变得容易。通常,客户端向服务拥有的点对点通道发送消息。服务订阅频道处理消息。没有响应被发回。
发布/订阅交互样式内置于消息传递中。客户端将消息发布到由多个订阅者读取的发布-订阅通道。
结合了发布/订阅和请求/响应的元素,形成了更高层次的交互风格。客户端将指定回复通道头的消息发布到发布-订阅通道。消费者将包含相关 id 的回复消息写入回复通道。客户端利用相关 id 将回复消息与收集响应的请求进行匹配。