RPC - 麻雀虽小,五脏俱全

提及 RPC (远程过程调用),你们应该不陌生。随着微服务、分布式愈来愈流行,RPC 应用愈来愈广泛。常见的 RPC 框架如:Dubbo、gRPC、Thrift 等。本篇文章不是介绍各类 RPC 的使用和对比。而是深刻剖析一个 RPC 包含哪些内容。我最近在 Hadoop 的源码,正好把 Hadoop RPC 看完了。感受 Hadoop 的 RPC 框架设计的仍是比价优秀的。Hadoop 做为大数据技术的基石,若是没有一个高性能、高可靠的 RPC 框架,很难支撑上千台服务器规模的集群。所以,本篇文章就以 Hadoop RPC 为例,介绍一个 RPC 框架会涉及的技术。程序员

架构设计

RPC 的架构涉及客户端、网络、服务端三大组件。网络通常使用 socket ,更多的是基于现有的网络框架进行参数的设置达到最优的目的。可是客户端和服务端须要咱们本身设计,而且对于分布式框架来讲,设计的架构应该有高性能、高可用以及可扩展的特色。编程

  • 高性能:因为客户端同时发起多个请求,这就要求系统可以快速处理,下降响应延迟。也就是高吞吐、低延迟。从客户端角度来讲,因为建立客户端到服务端的链接成本较高。所以能够缓存链接资源,从而实现多个客户端复用相同的链接资源,避免每一个客户端都来建立而下降性能;从服务端角度来讲,能够启动多线程来并发处理客户端请求。除了多线程,能够采用 Reactor 编程模式,提升多线程并发的性能。
  • 高可用:当咱们的服务端挂了,能不能有备用节点继续提供服务。Hadoop 2.x 实现了 NameNode 的高可用。当客户端须要经过 RPC 调用 NameNode 服务的过程当中,若是主 NameNode 宕机,那么备用 NameNode 会升级成活动节点。同时会将 RPC 的请求发送的当前活跃的 NameNode,从而继续提供可用的服务,而这个过程对客户端来讲是透明的。
  • 可扩展性:一个框架须要不断地优化、不断升级。须要在架构设计时明确不变的需求点,以及可变的需求点,对于可变的需求须要可以有良好的可扩展性。以 RPC 涉及的序列化为例。因为不一样序列化框架适用场景不一样,所以这须要被当成可变的需求点,应该将其设计成可扩展的,可以容易地支持不一样的序列化框架。目前,Hadoop RPC 支持自身的序列化框架(Writable)和 Protoc Buffer。

设计模式

设计模式更多地与上面提到的可扩展性相呼应。良好的设计模式能够提升代码复用性、加强可扩展性,同时可以下降 BUG 数量。Hadoop RPC 中涉及的设计模式比较多,大概包括:工厂模式、代理模式、适配器模式、装饰者模式和命令模式等。以代理模式为例,当客户端调用远程方法时,其实是经过代理,将方法名和参数经过网络发送到服务端。但这个过程对客户端是透明的,对于客户端来讲就像调用本地方法同样。设计模式

除了设计模式,在工程实践中还应该注意遵循常见的设计原则。缓存

多线程

在任何一个系统中多线程都比较常见。经过多线程并发处理,提升系统的吞吐量。在 Hadoop RPC 中,客户端与服务端都用到了多线程技术。客户端开启多线程,每一个线程处理一类请求,而且缓存链接资源。服务端也是多线程并发处理客户端的请求,使用 Reactor 编程模式提升并发性能。安全

谈到多线程就不得不提另外一个话题 —— 线程安全。Hadoop RPC 中用了很多的技术来保证线程安全,包括:synchronized、concurrent并发包、atomic并发包和 nio 工具包。从优秀框架中学习线程安全,对咱们之后并发编程有很多好处。服务器

序列化与反序列化

因为 RPC 涉及数据在网络上传输,所以须要一个优秀的序列化框架,既可以高效的编码与解码,且编码后的数据大小又尽量小。不一样的序列化框架主要是在编解码效率和编码大小两个主要方面作权衡。Hadoop RPC 目前支持两种序列化框架,一个是 Hadoop 本身实现的 Writable 框架,另外一个是 Protocol Buffer。Hadoop RPC 虽然支持 Writable 序列化框架,但仍是以 Protocol Buffer 为主。由于 Protocol Buffer 从编解码效率和编码大小方便都是比较优秀的。固然常见的序列化包括 Avro、Kryo 等,有兴趣的读者能够查一下它们之间的性能对比。网络

其余

一个 RPC 框架,除了包含上面提到比较主要的方面。还有一些其余的方面多线程

  • 语言层面:利用好 Java 语言的继承、组合、封装、多态等特性。甚至包括泛型、注解等。
  • 代码规范:良好的工程实现应该有一个良好的代码规范。在 Hadoop 中,代码风格比较统一,且每一个重要的类都有详细的注释,在关键的方法或者属性上也有明确的注释。我在本身的工程中会使用阿里的 Java 代码规约插件,也会为了让本身的代码更规范。
  • 异常处理:对于一个优秀的框架异常处理很关键,何时须要抛出异常、抛出什么样的异常以及何时须要处理异常。在 RPC 中除了须要处理本地异常还要处理远程服务的异常。所以,在程序中如何优雅的处理异常也是体现一个程序员能力的地方。
  • 网络编程:RCP 中涉及的网络编程通常用 socket,Hadoop RPC 使用的 Reactor 模式的网络编程,而且 Netty 也在使用这种框架。咱们有必要会用而且掌握它。

 这一段写的比较杂,想到哪写到哪。最近有跟朋友聊过在看 RPC 相关的东西,朋友说:“一个 RPC 可以涉及多少东西?值得研究?”。其实我一开始也是这样想的,无非就是客户端将请求序列化,经过网络发给服务端,服务端反序列化调用函数后再返回。可是看了 Hadoop RPC 代码后,我发现这样框架涉及的知识仍是特别多的,而且还比较系统,基本上包含了咱们平时编程涉及的方方面面。同时它再也不是一个单机程序,而是一个 C/S 架构的程序。若是咱们有兴趣还能够继续研究他的高可用,从而对分布式应用有更深刻的了解。架构

我以为 RPC 是麻雀虽小五脏俱全。因为它涉及了咱们编程的方方面面,因此我想基于 Hadoop RPC 作一个详细的教程,把它涉及的每一个重要部分都进行详细的分析,上面提到的内容基本都会涵盖。对于想了解 RPC 的读者,可以感觉到一个 RPC 框架更清晰的面貌。对于仅有 Java 基础的读者来讲,可以学到编写一个框架所涉及的具体编程技术,同时可以从世界顶级开源项目学到优秀设计和工程经验。并发

小结 

本篇文章主要介绍了 RPC 框架涉及的知识。包括:架构设计、设计模式以及设计原则、多线程并发以及线程安全、序列化框架和一些其余的内容。我以为学习最好的方式就是从优秀的框架中学习、模仿。比如咱们练书法基本都要通过临摹这一步。固然直接看别人的代码确实需求花费更多的时间和经历,而且有时候投入与产出并不成正比。因此,我想把我在 Hadoop RPC 框架中学到的优秀的设计和实现可以整理成教程,以便有兴趣的读者学习。若是有任何建议欢迎与我交流。公众号有福利

公众号「渡码」

相关文章
相关标签/搜索