基于 Triple 实现 Web 移动端后端全面打通

作者:陈有为,陌陌研发工程师、Apache Dubbo PMC

  01 

RPC 协议开发微服务

Aliware

在我们正常开发微服务的时候,传统 RPC 服务可能在最底层。上层可能是浏览器、移动端、外界的服务器、自己的测试、curl 等等。我们可能会通过 Tomcat 这种外部服务器去组装我们的 RPC 层,也就是 BFF。或者我们没有 BFF,我们的 RPC 就是对外提供服务。但因为浏览器要访问,所以我们需要有一个网关,比如说 APISIX 或者 ShenYu 等 HTTP 网关。

上图展示的是我们的流程,但是存在一些问题。

如果我们的服务是非常轻的,我们只需要一个转发层,无论是配网关还是起一个 webserver 去转发,怎么做都很麻烦。

此外,RPC 服务大部分都是基于二进制的,而二进制正常在本地是没法测试的。因此我们的公司内都可能就会开发一种后台或者中间的 Proxy 代理让我们去测试。但这个的前提是你至少得把它部署到测试环境,所以还是没法在本地测试。

总体来说,这两个问题会导致易用性比较低,且开发成本相对较高,因为要做一些与业务无关的重复劳动。

  02 

全新升级的 Triple 协议

Apache Dubbo


基于上边的两个问题,我们来介绍一下 Triple 协议。

先来说一下上一代协议,它产出的原因是什么。我们应该都知道 Dubbo 原来是 Dubbo 协议,它是基于 tcp 的,它只有一个包。因为它的包的设计,导致了网关无法做一些特殊规则判断、过滤等操作。但也不是绝对的,如果你愿意牺牲性能把包完全解出来,组装回去再透传还是可以做到的,但一般大家都不太能接受。

所以我们就在想能不能把原数据和真正的包分开。现在我们有现成的 HTTP,又有一个业界主流的 gRPC,所以我们的目标就是兼容 gRPC。因为 gRPC目前都是用 IDL,而 IDL 有一个问题,尤其在 Java 侧。因为大家都是写一些接口,定义一些包去实现,这样就会非常麻烦。Go 侧就还好,因为大家已经习惯了这种开发模式。

所以我们开发了 Triple 协议,首先它兼容了 gRPC,所以我们能实现和 gRPC 的完全互通。其次,我们兼容了自己定义接口的方法。虽然会损失一定的性能,但提升了一些易用性。而且 RPC 一般不是业务的瓶颈,大多数瓶颈还是在 DB。

但还有个问题,虽然我们兼容了 gRPC,但 gRPC 是基于 TPC 的,所以如果前端或者其他第三方系统只有 HTTP,它还是接受不了我们的系统。

基于此,我们想推出一个全新的 Triple 协议。为了解决上述的所有问题,我们参考了gRPC、gRPC Web、通用 HTTP 等多种协议,做到浏览器访问,支持  Streaming,还支持同时运行在 HTTP/1、HTTP/2 协议上。因为目前 HTTP/3 还没有大规模推广,未来也会支持 HTTP/3。

最终的设计实现是完全基于 HTTP 的,且对人类、开发调试友好。 我们可以通过简单的浏览器访问或者 curl 访问,尤其是对 unary RPC。此外,我们和 gRPC 是完全互通的,用 HTTP 的业务不用担心兼容性的问题,也不用担心签协议的问题。为了稳定性,我们只会采用业界流行的网络库,比如 Java 的 native、Go 的基础的 net 包。

虽然 Triple 协议和 gRPC 协议都基于 HTTP,但 gRPC 是基于 HTTP/2 的,而 Triple 是基于 HTTP/1 和 HTTP/2 的。

我们在兼容 gRPC 的同时,我们为了易用性也扩展了一些功能。比如请求里我们支持 Application/Json 的请求格式,支持使用 curl 访问;

此外上一版的协议,为了支持传统定义接口的方式,我们有一个二次序列化的过程。我们想在这里通过一个特殊的 content type 来决定我们的 body 的结构,解决二次序列化的问题。同时这个东西是可以扩展的,理论上 HTTP 的所有功能我们在 Triple 协议上都可以实现,也可以拓展。

用了 Triple 协议之后,我们的开发流程也发生了改变。如果你不需要进行组装,或者没有外层的代理,可能你的接入流程就是从外部的请求浏览器、对方的服务器、curl、自己测试等直接到了 server。

和其他的 gRPC 的通信也是没有问题的,流程就相当于少了一层。对于大多数用户,如果你不需要这个场景,其实是有很大的好处。

Triple 协议因为最开始兼容 gRPC,那个时候只基于 HTTP/2,HTTP/2 有 Streaming 的能力,所以它天然支持 Streaming。但这里比较特殊的是,我们新版的协议在 HTTP/1 也支持了 Stream,但因为 HTTP/1 的限制只能支持到 Server Streaming。依赖 HTTP/1 的 Server Push 实现。

Client Stream 和 Bi Stream 就没什么可说的了。但有一个特别的是,在 Java 侧没有 Bi Stream,从编码上就没有,但从实现上是有的。