RPC 使用中的一些注意点

最近线上碰到一点小问题,分析其缘由发现是出在对 RPC 使用上的一些细节掌握不够清晰致使。不少时候咱们作业务开发会把 RPC 看成黑盒机制来使用,但若不对黑盒的工做原理有个基本掌握,也容易犯一些误用的微妙错误。微信

虽然曾经已经写过一篇《RPC 的概念模型与实现解析》 从概念模型和实现细节上讲述了 RPC 的原理,这一篇就从使用上的一些注意点来捋一捋吧。网络

同步

RPC 的调用一般为了方便使用,会被假装成普通方法调用的形式。但实际两者之间存在巨大的差别,进程内的方法调用的时间量级是 ns(纳秒),而进程间的 RPC 方法调用时间量级一般是 ms(毫秒),它们之间差着 10 的六次方呢。RPC 的冰山底部透视图以下:架构

但在目前流行的微服务架构模式下,跨服务的同步调用隐藏着巨大的风险。通常微服务化架构下,一般一个业务的调用会跨 N(N 通常大于 2) 个服务进程,整个调用链路上的同步调用等待的瓶颈会由最慢(或脆弱)的服务决定,A-B-C 像这样一个链路,A 同步调用 B 并等待返回,B 同步调用 C 并等待返回,以此类推,就像一组齿轮链,级级传动,这很容易产生雪崩效应。若 C 服务挂住了,会致使前面的服务所有都由于等待超时而占用大量没必要要的线程资源。框架

所以,微服务架构下,内部主服务链之间的 RPC 调用须要异步化,服务之间的调用请求和等待结果相互之间解耦,以下是一个服务链路调用的示意图:异步

外部用户经过服务网关(API Gateway)发起调用并等待结果,随后网关派发调用请求给后续服务,其主调用链路为 A-B-C,其内部为异步调用,链路上不等待,最后由 C 返回结果给服务网关。其中 B 又依赖两个子服务,S1 和 S2,B 须要 S1 和 S2 的返回结果才能发起 C 调用,所以在支线上 B 针对 S1 和 S2 调用就须要是同步的。微服务

异步

RPC 的同步调用确保请求送达对方并收到对方响应,若没有收到响应,框架则抛出 Timeout 异常。这种状况下调用方是没法肯定调用是成功仍是失败的,须要根据业务场景(是否可重入,幂等)选择重试和补偿策略。性能

而 RPC 的异步调用意味着 RPC 框架不阻塞调用方线程,调用方不须要马上拿到返回结果,甚至调用方根本就不关心返回结果。RPC 的异步交互场景示意图以下:spa

在上面的示意图中,对因而否须要返回值的异步请求,其中的细微差别在因而否返回一个 Future 对象给调用方,以便将来(Future)调用方能够再经过它来获取返回值。正是由于这种 Future 机制的存在,因此针对前面(图2)中 S1 和 S2 的调用就能够采用一种异步并行的调用机制来提高并行性和性能,以下图所示:线程

这样调用 S1 和 S2 的总时间就由最慢的一个服务响应时间来决定了。(上图中其实调用 S1 和 S2 不可能作到同时,有细微的时间差别,但相对跨进程的调用自己来讲这种差别基本忽略不计。)对象

线程

RPC 的线程模型通常以下所示:

其中,RPC 的网络层一般采用非阻塞型 I/O 模型,放在 Java 的实现语境下就是 NIO 了。而 RPC 框架一般共享一个 I/O 线程池,处理全部链接上的 I/O 事件派发。一般业务事件会派发到内部的一个固定大小(可配置)的业务执行线程池,再由业务执行线程调用应用实现层的代码。

但有些 RPC 框架在实现客户端的 I/O 线程模型时,也采用了针对每一个不一样的服务端一个独立的 I/O 线程池,这样就变成了下面这个图所示:

这带来了一个潜在的问题,在一个客户端须要链接大量服务端时(这在基于 RPC 实现的服务框架中很常见),客户端的 I/O 线程池数就和需链接的服务数相等。在如今的微服务部署模式下,通常一个服务部署在一个 Docker 容器中,同一个服务会有不少个(几十上百个)进程共同组成集群提供服务,这样就致使客户端 I/O 线程数可能会不少。

而在 Docker 环境下 Java 的 Runtime.availableProcessors() 获取的 CPU 数量实际是物理机的,而不是 Docker 隔离的核数。另外,像 Netty 这样的网络框架常常默认是基于 CPU 核数来启动默认的 I/O 线程数的,因此致使针对每一个服务的客户端会启动 CPU 核数个 I/O 线程再乘上服务实例数,这个线程数量也是颇为客观,出现单进程好几千固化的线程,线程调度和切换的成本颇高,另外服务的水平扩展性也有必定的受限。这也是须要注意的另外一点。

...

在曾经那篇《RPC 的概念模型与实现解析》 的的结尾,我曾写到:

不管 RPC 的概念是如何优雅,可是“草丛中依然有几条蛇隐藏着”,只有深入理解了 RPC 的本质,才能更好地应用。

因此这一篇大概就是抓出了几条隐藏着的蛇吧。


写点文字,画点画儿,记录成长瞬间。
微信公众号「瞬息之间」,既然碰见,不如一块儿成长。

相关文章
相关标签/搜索