API网关-协议转换(泛化调用)

时间:2024-04-09 10:43:10

RPC和REST的区别

REST和RPC是两种通讯方式,并不是协议,这一点大家要注意。

REST是基于HTTP协议的,而RPC可以基于HTTP协议来实现,也可以通过TCP协议来实现。

业界普遍采用的做法是,内部系统之间调用用 RPC,对外用 REST,因为内部系统之间可能调用很频繁,需要 RPC 的高性能支撑。对外用 REST 更易理解,更通用些。

API网关内部和外部通讯方式

在进行协议转换前我们要先思考一个问题,从什么协议转成什么协议呢?

我们说的协议转换是把客户端的请求协议转为微服务内部的接口协议,处理完之后再把结果转化成客户端能够接受的协议类型。

  • 对于客户端的请求,我们建议采用适用面广泛的REST方式,另外,还可以借助于Swagger这样的工具生成接口代码,对于外部用户来说使用更方便。
  • 对于微服务内部的通讯,建议采用性能更好的RPC通讯方式。因为RPC相对于REST方式效率更高一些。

主流的几种RPC框架

RPC框架按可否跨语言来分类,可以分为两种,一类是跟某种特定语言平台绑定的,另一类是与语言无关即跨语言平台的。

跟语言平台绑定的开源 RPC 框架主要有下面几种:

  • Dubbo:国内最早开源的 RPC 框架,由阿里巴巴公司开发并于 2011 年末对外开源,仅支持 Java 语言。
  • Motan:微博内部使用的 RPC 框架,于 2016 年对外开源,仅支持 Java 语言。
  • Spring Cloud:国外 Pivotal 公司 2014 年对外开源的 RPC 框架,仅支持 Java 语言

而跨语言平台的开源 RPC 框架主要有以下几种:

  • gRPC:Google 于 2015 年对外开源的跨语言 RPC 框架,支持多种语言。
  • Thrift:最初是由 Facebook 开发的内部系统跨语言的 RPC 框架,2007 年贡献给了 Apache 基金,成为 Apache 开源项目之一,支持多种语言。
  • Tars:腾讯内部使用的 RPC 框架,于 2017 年对外开源,开始仅支持 C++ 语言,现在已经支持多种语言了。

如果你的业务场景仅仅局限于一种语言的话,可以选择跟语言绑定的RPC框架中的一种。如果涉及多个语言平台之间的相互调用,就应该选择跨语言平台的 RPC 框架。

下面我们说说几种使用最广泛的几种RPC框架。

gRPC

  • 基于HTTP/2.0协议。可建立长连接来通讯。
  • 使用 IDL 定义服务接口及通信消息对象。
  • 使用 Protocol Buffers 和 gRPC 工具生成序列化/反序列化和 RPC 通信的代码。
  • 基于生成的代码创建服务端和客户端应用。
  • 用gRPC通讯的客户端和服务端单向和双向数据流传输。

客户端支持语言:

  • C++
  • Java(and Android)
  • Python
  • Go
  • Ruby
  • C#
  • Javascript(node.js)
  • Objective-C (iOS!)
  • PHP

服务端支持的语言:

  • C++
  • Java
  • Python
  • Go
  • Ruby
  • C#
  • Javascript(node.js)
    API网关-协议转换(泛化调用)

Thrift

国外用的多,源于facebook,后捐献给Apache基金。是Apache的*项目 Apache Thrift。使用者包括facebook, Evernote, Uber, Pinterest等大型互联网公司。 而在开源界,Apache hadoop/hbase也在使用Thrift作为内部通讯协议。 这是目前最为成熟的框架,优点在于稳定、高性能。

Apache Thrift是一个跨语言的服务框架,Thrift包含一个完整的堆栈结构用于构建客户端和服务器端。对于生成的客户端和服务端代码,我们就不做过多介绍了,下面主要说说Thrift特有的特性:TProtocol和TTransport。
API网关-协议转换(泛化调用)

传输协议(TProtocol)

Thrift可以让用户选择客户端和服务端之间传输通信协议的区别,在传输协议上总体分为文本和二进制(binary)传输协议,为了节省带宽,提高传输效率,一般情况下使用二进制类型的传输协议为多数。

  • TBinaryProtocol:二进制编码格式进行数据传输
  • TCompactProtocol:高效率的、密集的二进制编码格式进行数据传输
  • TJSONProtocol:使用 JSON 的数据编码协议进行数据传输
  • TDebugProtocol:使用易懂的可读文本格式,以便于debug

数据传输方式(TTransport)

TTransport是与底层数据传输紧密相关的传输层。每一种支持的底层传输方式都存在一个与之对应的TTransport。在这一层,数据是按字节流处理的,即传输层看到的是一个又一个的字节,并把这些字节按顺序发送和接收。TTransport并不了解它所传输的数据是什么类型,实际上传输层也不关心数据是什么类型,只需要按照字节方式对数据进行发送和接收即可。数据类型的解析在TProtocol这一层完成。

  • TSocket:使用阻塞式 I/O进行传输,是最常见的模式
  • THttpTransport:采用HTTP协议进行数据传输
  • TFramedTransPort: 以frame为单位进行传输,非阻塞式服务中使用;
  • TFileTransPort:以文件形式进行传输
  • TMemoryTransport:将内存用于I/O传输
  • TZlibTransport:使用zlib进行压缩, 与其他传输方式联合使用
  • TBufferedTransport对某个transport对象操作的数据进行buffer,即从buffer中读取数据进行传输,或将数据直接写入到buffer

Dubbo

国内用的多,源于阿里公司。 性能上略逊于Apache Thrift,但自身集成了大量的微服务治理功能,使用起来相当方便。 Dubbo的问题在于,该系统目前已经很长时间没有维护更新了。Dubbo的架构图如下所示:
API网关-协议转换(泛化调用)

组件角色 说明
Provider 暴露服务的服务提供方
Consumer 调用远程服务的服务消费方
Registry 服务注册与发现的注册中心
Monitor 统计服务的调用次调和调用时间的监控中心
Container 服务运行容器

泛化调用

API网关在进行协议转换的时候有两步,第一步是把客户端的请求协议转为相应微服务的接口协议,然后再调用相应的微服务;第二步是把微服务返回的结果转换为客户端的协议,然后返回给客户端。

客户端的请求协议可能有多种,而微服务的接口协议也可能有多种,不同的协议之间是无法直接通讯的,那么就需要一个模块来负责把不同的协议转换为用某种语言描述的对象,然后把这个对象再转化为相应的协议代码块。如下图所示:
API网关-协议转换(泛化调用)

使用不同的RPC框架,那么需要转成的客户端代码是不一样的。而且即使是对于一种RPC框架,要调用不同语言写的微服务时,所要转成的客户端代码也不也一样。