说起 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 框架中学到的优秀的设计和实现能够整理成教程,以便有兴趣的读者学习。如果有任何建议欢迎与我交流。公众号有福利

公众号「渡码」

 

RPC - 麻雀虽小,五脏俱全的更多相关文章

  1. 我是这样手写 Spring 的(麻雀虽小五脏俱全)

    人见人爱的 Spring 已然不仅仅只是一个框架了.如今,Spring 已然成为了一个生态.但深入了解 Spring 的却寥寥无几.这里,我带大家一起来看看,我是如何手写 Spring 的.我将结合对 ...

  2. 我是这样手写Spring的,麻雀虽小五脏俱全

    人见人爱的Spring已然不仅仅只是一个框架了.如今,Spring已然成为了一个生态.但深入了解Spring的却寥寥无几.这里,我带大家一起来看看,我是如何手写Spring的.我将结合对Spring十 ...

  3. js万年历,麻雀虽小五脏俱全,由原生js编写

    对于前端来说,我们可能见到最多的就是各种各样的框架,各种各样的插件了,有各种各样的功能,比如轮播啊,日历啊,给我们提供了很大的方便,但是呢?我们在用别人这些写好的插件,框架的时候,有没有试着问一问自己 ...

  4. RPC框架原理与实现

    了解一个框架最好的思路就是寻找一个该类型麻雀虽小五脏俱全的开源项目,不负所期,轻量级分布式 RPC 框架 RPC,全称 Remote Procedure Call(远程过程调用),即调用远程计算机上的 ...

  5. 一篇文章了解RPC框架原理

    1.RPC框架的概念 RPC(Remote Procedure Call)–远程过程调用,通过网络通信调用不同的服务,共同支撑一个软件系统,微服务实现的基石技术.使用RPC可以解耦系统,方便维护,同时 ...

  6. 花6个月写的付费专栏,免费送|仿开源框架从零到一完整实现高性能、可扩展的RPC框架

    作者 渡码,阿里巴巴码农,公众号:渡码 作者,专注大数据开发.数据分析和Python技术. 关注公众号 渡码 回复关键字 manis,可获取电子书.各章节和完整源代码,并且可加入读者群一起交流问题. ...

  7. 仿开源框架从零到一完整实现高性能、可扩展的RPC框架 | 6个月做成教程免费送

    去年年就在写一本付费小册,今年年初基本上就写完了,本来预计计划是春节上线结果由于平台的原因一直拖着没上.五一前跟平台联系给的反馈是五月份能上,结果平台又在重构,停止小册的申请和上线,最后我考虑了一下决 ...

  8. 读阿里巴巴Java开发手册v1.2.0之工程结构有感【架构篇】

    首先,把昨天那俩条sql语句的优化原因给大家补充一下,第一条效率极低,第二条优化后的,sql语句截图如下: 经过几个高手的评论和个人的分析: 第一条sql语句查询很慢是因为它首先使用了in关键字查询, ...

  9. [转帖]Windows 内核说明

    来源:https://zhidao.baidu.com/question/398191459.html 自己的理解. windows 的内核文件 是在 c:\windows\system32 目录下面 ...

随机推荐

  1. C# Repeater 嵌套

    <table class="table table-bordered table-fixed"> <thead> <tr> <th wid ...

  2. spring不同环境下用不同的配置文件

    @Configuration @PropertySource("xx-${spring.profiles.active}.properties") public class Top ...

  3. 才知道 Windows Live Writer Source Code plugin for SyntaxHighlighter 更新到2.0了

    这是我用 Windows Live Writer 发布的第一篇文章! 在官方网站看到 Windows Live Writer Source Code plugin for SyntaxHighligh ...

  4. strcpy、strncpy、strlen、memcpy、memset、strcat、strncat、strcmp、strncmp,strchr

    1.strcpy #include<stdio.h> #include<assert.h> char *mystrcpy(char *dest, const char *src ...

  5. Handler和Thread线程

    大家都知道,在PC上的应用程序当需要进行一些复杂的数据操作,但不需要界面UI的时候,我们会为应用程序专门写一个线程去执行这些复杂的数据操作.通过线程,可以执行例如:数据处理.数据下载等比较耗时的操作, ...

  6. 解决Spring JdbcTemplate调用queryForObject()方法结果集为空时报异常

    JdbcTemplate用的时候发现一个问题:调用queryForObject()方法,如果没有查到东西则会抛一个异常:org.springframework.dao.EmptyResultDataA ...

  7. 性能测试学习第六天_loadrunner录制的一些问题

    1.录制脚本的两种查看方式(脚本查看和树查看) 2.录制选项 在vugen界面点击开始录制,如下图,点击选项,即进入录制选项界面 重点讨论录制选项下 基于HTML的脚本和基于URL的脚本 注:菜单栏图 ...

  8. webpack.config.js====配置babel

    参考:https://www.jianshu.com/p/9808f550c6a91. 安装依赖babel-loader: 负责 es6 语法转化babel-preset-env: 包含 es6.7 ...

  9. Android Asynchronous Http Client

    Features Make asynchronous HTTP requests, handle responses in anonymous callbacks HTTP requests happ ...

  10. 一、 Spring IOC 简介

    一 . 什么是IOC(Inversion of Control) IOC :控制反转,也称为依赖注入(DI).听起来有点云里雾里,他到底是个啥,为什么Spirng中最基础的就是它? 我们的项目其实都是 ...