理论修炼之RPC,微服务高效通讯的首选

1,029 阅读5分钟

这是我参与8月更文挑战的第14天,活动详情查看:8月更文挑战

  • 📢欢迎点赞 :👍 收藏 ⭐留言 📝 如有错误敬请指正,赐人玫瑰,手留余香!
  • 📢本文作者:由webmote 原创,首发于 【掘金】
  • 📢作者格言: 生活在于折腾,当你不折腾生活时,生活就开始折腾你,让我们一起加油!💪💪💪

🎏 序言

RPC,字面直译是远程过程调用,该项技术并不是现在才开始出现的,之前的net remoting、web service甚至DCom,都或多或少的实现了类似的功能,只不过它们或者没重视数据的编解码,或者每重视通讯协议的通用性,因此在它们流行的时候,总给人感觉或者性能没那么理想,或者难以应用。

而目前流行的RPC技术,例如Thrift、GRPC、Dubbo等均为互联网电商的高并发,高性能的分布式应用通讯而设计,其编解码性能都非常优秀,通讯的效率也都不错。

🎏 01. 为啥用RPC?

很多朋友对于微服务采用RPC通讯都带很大的疑问,难道直接使用webApi他不香吗?

是的,什么事情都不是绝对的,当你的业务性能要求并不是很高的情况下,的确http的webapi已经足够了吧,毕竟抠那么一点性能,不如更快完成业务的好。

从拆分为微服务的角度来看,由于拆分的业务粒度问题,不可避免的会导致以前一个服务搞定的功能,现在是由多个服务联合完成的。我们画个图看看到底发生了什么?

image.png

是的,之前的业务A如果是各个数据需要调用数据库,假设需要3次,那么拆分为微服务后,需要通过网络分别调用各个微服务的接口,这些接口再通过网络调用各自的数据库。

这只是一般复杂的场景,还有很多复杂的业务,可能调用链更长。

那么这多出来的网络调用,每个都会有延迟,加起来可能就比较客观了。当然这就是你提高了扩展性而付出的代价。

🎏 02. RPC的调用环节

  1. RPC按照规定的协议序列化二进制流
  2. 网络传送(tcp或者 http2)
  3. 反序列化二进制流,按照指定的方法等参数交给动态代理处理,并得到返回值(有些协议可以定义没有返回值)
  4. 返回值进行序列化,通过网络传回调用方。
  5. 调用方反序列化,得到返回值。

因此从上面的环节也可以看出,主要的性能可以优化的地方就是网络传输和序列化、反序列化。

在网络传输方面,目前比较优秀的库有netty,有能力的童鞋可以在这个基础上定义自己的协议来实现通讯底层。

当然目前已经存在的也比较优秀,例如:thrift,dubbo,grpc。

如果我们进行协议封装,推荐的做法是支持异步IO,c#下支持async模式,这样可以极大提高吞吐量。

在序列化性能方面,有个基本的优先级: xml < json < protobuf、thrift。

在数据量稍微大点的情况下,序列化json是一个很大的性能损耗,这个在之前的项目中有做过性能测试。

当然这些协议在使用中还有一些特性需要注意选择合适的场景。比如简单的可以采用json,因为对于protobuf、thrift,它们都需要定义idl,相对麻烦些,当然这些麻烦就是为了性能设计。

🎏 03. Thrift介绍

Thrift 是一个软件框架,用来进行可扩展且跨语言的服务的开发。它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Python, PHP, Ruby, Erlang, Perl, Haskell, C#, Cocoa, JavaScript, Node.js, Smalltalk, and OCaml 这些编程语言间无缝结合的、高效的服务。

thrift最初由facebook开发,目前是 Apache基金会的顶级项目。

thrift允许你定义一个简单的数据类型和服务接口的idl接口文件,以作为输入文件,编译器生成代码用来方便地生成RPC客户端和服务器通信的编程语言。

🎏 04. grpc介绍

gRPC由 google 开发,是一款语言中立、平台中立、开源的远程过程调用(RPC)系统。

gRPC采用protobuf来定义接口,从而有更加严格的接口约束条件,通过protobuf可以将数据序列化为二进制编码,这会大幅减少需要传输的数据量,从而大幅提高性能。

gRPC采用Http 2.0协议,在通讯效率上相比采用Http协议的webapi还是有一定的优势的。

🎏 05. 小结

其实还有很多内容,我想写的更多,可是实力和时间不允许,暂时到这吧,后续有什么不妥的还可以修改追加,感谢你看到这里!

例行小结,理性看待!

结的是啥啊,结的是我想你点赞而不可得的寂寞。😳😳😳

👓都看到这了,还在乎点个赞吗?

👓都点赞了,还在乎一个收藏吗?

👓都收藏了,还在乎一个评论吗?