• 我开始抄代码来学编程


    之前研究 Hadoop 源码,把 hadoop-common 模块下的 RPC 模块源码通读一遍,又花了 3 个月抄了一遍 Hadoop RPC 代码,学到很多东西。我觉得学习编程最有效的方式就是抄代码,我觉得这个过程对正在学编程的朋友很有帮助,所以想做成教程,以下是周末写的一个开头,后续教程的形式以及进展会发布在公众号,有兴趣的朋友欢迎文末关注

    1. 起源

    故事得从19年上半年说起,那时候我正打算研究一下Hadoop源码。 现在大家都听说过Hadoop,它是一个分布式存储和计算的框架。作为分布式系统,节点之间的通信、交互式必不可少的。Hadoop自己实现了RPC(Remote Procedure Call,远程过程调用)模块来满足这样的需求。带着好奇,我便阅读了整个Hadoop RPC模块的源代码,读完后发现这个模块设计的非常好,与其他模块无耦合,完全可以独立出来当成一个独立的框架。为了能够学习相关的编程知识,同时还可以看到Apache 顶级开源项目的代码如何编写的,因此我便把Hadoop RPC模块做成教程。

    虽然这个项目是实现RPC功能,但我觉得我们重点不应该过多关注RPC本身,而应该重点学习RPC所涉及的客户端开发、服务端开发、网络编程、多线程、并发编程、设计模式等核心知识,尤其是对于刚学习Java没有接触线上实战项目的朋友,掌握好了这些知识,写其他项目也会更有思路。

    2. 起名

    为了能让不熟悉Hadoop的朋友也能学习本教程,因此我们将Hadoop RPC赋予了新的业务含义。

    假设我们有这样一个场景,公司开发一个新的数据库,这个数据库的底层可能是Mysql,也可能是MongoDB,甚至可能是公司自研的数据库技术,无论是什么,数据库都可以作为服务端。作为用户来说,数据库底层用了什么技术并不关系,而是关心怎么使用。数据库需要提供了API方便用户调用,因此就需要有客户端。

    实现连接客户端请求和服务端响应的技术就是RPC。我给这个项目起了一个名字叫Manis,那么,数据库的名字便是ManisDb。工作中我们也比较鼓励大家给自己的项目起个名字,有了名字,它就像自己的孩子一样,我们会更有责任心把它做好。

    3. 优势

    优势都是相对的。Hadoop RPC 相比于一般的实战项目来说,它是经过线上检验的,Hadoop集群规模最大达到上万台,单一个RPC模块完全可以独立出来用于实战。同时,我们还可以积累顶级开源项目的开发经验,大到架构设计,小到设计模式,代码规范。RPC在客户端开发、服务端开发、网络编程三方面都有涉及,且都是重点内容。

    Hadoop RPC相比于源码分析类的教程来说,优势在于实战意义比较强。我们会按照Hadoop RPC源码把我们的野生项目Manis从0到1完整的敲一遍,还原度为95%。解释下为什么不是100%,一方面为了突出重点,我会把不太重要、不是很核心的技术舍弃掉。另一方面为了符合新的业务定义,我会做一些改进,而不是照搬Hadoop RPC。比如:Hadoop RPC到了2.6版本只支持Protobuf序列化协议,但为了体现高扩展以及模块间的低耦合,Manis支持了多种序列化协议。

    在写教程之前,我花了大概3个月时间先对照Hadoop RPC源码把Manis敲出来了。学会了Manis后,你完全有能力阅读Hadoop RPC的源码,这也算是面试的加分项吧。可能有些读者觉得这种方式比较LOW,但我还是相信马化腾说的“抄代码培养感觉”,写代码好比学字画,不临摹好的作品怎么学习别人的优点。真正要把看到的东西变成自己的,最终扎实的方式就是自己走一遍。至于Manis中被舍弃的部分我会在教程中说明,必要的时候会截取Hadoop源码一起分析。

    4. Manis架构图

    图1-1是Manis的架构图,基本上是一般的RPC架构图。

    图1-1 Manis架构图

    5. Manis核心组件时序图

     

    图1-2 Manis 核心组件时序图

    6. Manis核心组件概念

    结合图1-2对Manis中涉及的核心的组件概念进行说明。

    ManisDb:图中没有表示,它代表数据库,负责启动服务端(即ipc.Server类),这里需要说明一下我们的重点在于RPC开发,这里的数据库只是举一个例子,不会涉及真正的数据库开发。

    ManisClient:提供给普通用户的客户端类,用于对ManisDb进行增删改查,它使用Protobuf协议与ManisDb进行通信。

    Manager:提供给管理员的客户端类,用于对ManisDb进行管理,它使用Serializable协议(Java原生的序列化方式)与ManisDb进行通信

    ProtoBufRpcEngine:支持Protobuf协议的RPC引擎,它定义了两个内部类——Invoker类和ProtoBufRpcInvoker类。Invoker类用于封装客户端的调用请求,并使用Protobuf协议序列化。ProtoBufRpcInvoker类用于完成客户端请求的方法调用(服务端调)。

    SerializableRpcEngine:支持Serializable协议的RPC引擎,它定义两个内部类——Invoker类和SerializableRpcInvoker类。Invoker类用于封装客户端的调用请求,并使用Serializable协议序列化。SerializableRpcInvoker类用于完成客户端请求的方法调用(服务端调)。

    Client:建立与服务端的socket连接,接收客户端调用,并发送调用请求给服务端,等待服务端返回并将结果返回。

    ipc.Server:该类定义在ipc包下面,通过Reactor模式接收并处理客户端请求,最终调用ProtoBufRpcInvoker或SerializableRpcInvoker的方法获得结果,并返回给客户端。

    公众号「渡码」,分享更多高质量内容

  • 相关阅读:
    返回图片宽高比
    3.1/3.2图片上传类
    php获取图片的拍摄及其他数据信息
    上传类
    pathinfo()的用法
    上传并压缩图片
    将数组转化为键值对
    css3判断某个li标签
    禁止滚动条/启用滚动条
    Keepalived + haproxy双机高可用方案
  • 原文地址:https://www.cnblogs.com/duma/p/11712959.html
Copyright © 2020-2023  润新知