【框架解析】Hadoop系统分析(十一)--RPC

hadoop自己实现了一个简单的rpc机制,用于在服务器之间进行数据传输,大体的结构如下:


主要分为三个部分

  1. Server
    使用java.nio包发布服务
    1. Server.Connection
      1. 保存与客户端的连接,存放对应的Socket、SocketChannel与UserGroupInformation
      2. 使用UserGroupInformation控制当前操作的权限
      3. readAndProcess是主要的处理rpc请求的方法。
        首先从数据流中读取4个字节的header(内容为hrpc);
        之后读取两个字节的内容(ByteBufer0为version信息,ByteBuffer1为加密类型(无,kerberos,token));
        读取ConnectionHeader内容,主要是取得这次调用所使用的Protocol与ugi
        最后读取数据长度以及数据内容到data中,将data反序列化为rpc的调用参数后与Connection一起封装成Call对象后放到Call队列中等待处理
    2. Server.Call
      记录一个请求到单server后的相关信息,其中包括客户端id,参数(Writable类型),到客户端的连接(Connection),响应数据流(ByteBuffer),时间戳,response数据
    3. Server.Listener
      1. 监听器,Thread子类
      2. 初始化时打开ServerSocketChannel,将channel与address绑定,并根据ipc.server.listen.queue.size指定请求的队列长度,默认为128.
      3. 初始化Reader的线程池,线程池大小根据ipc.server.read.threadpool.size配置项指定,默认为1。生成Reader将线程池装满。
      4. 注册OP_ACCEPT的Selector,在OP_ACCEPT时从readerpool中取出一个reader激活后处理此次连接上来的channel
      5. Reader用于在OP_READER是读取传入的数据,调用Connection的readAndProcess来进行rpc的执行
      6. cleanupConnections用于关闭超出限制的connection
    4. Server.Responder
      将rpc结果写回给client后断开连接
    5. Server.Handler
      1. Thread子类,Server启动时会启动一定数量的handler用于处理Call队列中的rpc请求(namenode根据dfs.namenode.service.handler.count配置项决定,默认10个,datanode根据dfs.datanode.handler.count配置项决定,默认3个)
      2. (这里是抽象类,具体由子类实现功能)从队列中取出一个Call,Call包含了rpc的类,方法名,参数数量与参数类型,剩下的就比较简单:反射调用,得到结果,将结果封装到ObjectWritable后写入response数据流封装到Call中
      3. 将结果call加入到队列由Responder处理返回给client
  2. Client
    向Server发起rpc请求。各种call方法进行各式的rpc调用
    1. Client.Connection
      1. 继承Thread。维护与Server端建立的链接,打开与Server的Stream时启动进程,在所有Call都完成后结束连接进程
      2. 初始化时配置安全信息以及rpc使用的类
      3. setupConnection中打开从client到server之间的socket连接
      4. closeConnection中关闭socket连接
      5. setupIOstreams 打开到server端socket的数据流(InputStream与OutputStream),写入连接头信息(hrpc,当前版本以及验证类型),在构造出正确的ConnectionHeader后写入(protocol,ugi,验证方式)
      6. sendParam 将调用参数发送出去,首先发送参数转换为byte的长度,再发送参数的具体内容
      7. receiveResponse 收到服务器返回的结果,根据返回的id将结果传给对应id的Call
    2. Client.Call
      封装一次调用所需要的信息,包括调用id,调用所需要的参数,调用返回的值以及返回的异常
    3. Client.ParalleCall
      继承自Call,进行并发调用多个方法,并且并发获得调用结果
    4. Client.ParallResults
      并发调用所获得的结果
      封装了Rpc调用的内容,包含了调用的参数,已经返回结果时的值
  3. RPC
    理解了Server与Client类,再来看RPC类就容易了。RPC主要就是把Server与Client之间的调用封装了一下
    1. getProxy 构造一个客户端调用,用于方便通过代理发送rpc请求
    2. getServer 获取到Server服务
    3. call 并发调用一组服务
    4. Invocation 封装一次调用所使用到的method与parameter
    5. ClientCache Client的缓存,用于保存使用到的client,在client没有被引用的时候,就会关闭对应的client
    6. Invoker 封装rpc的操作
    7. Server 集成Server类,实现Server类中的call抽象方法

读完hadoop的rpc实现,基本上也了解了使用nio包实现socket通信的方法


猜你喜欢

转载自blog.csdn.net/shorn/article/details/8715060