项目作者: greatmengqi

项目描述 :
仿写hadoop1.0.0自带的RPC框架
高级语言: Java
项目地址: git://github.com/greatmengqi/hpc.git
创建时间: 2020-03-09T04:49:51Z
项目社区:https://github.com/greatmengqi/hpc

开源协议:

下载


hadoop 1.0.0 RPC框架仿写

hadoop RPC框架简介

hadoop RPC框架主要包括两个组件,服务端和客户端。服务端包括一个listener线程,一组Reader线程,一组Handle线程和一个Responder线程。listener线程包含一个SocketChannel和一个Selector,只负责监听客户端连接。每个Reader线程包含一个独有的Selector,每当Listener线程监听到客户端连接后就取一个Reader并向其注册一个read事件。Reader负责读取客户端请求,并将其包装成一个Call放入阻塞队列calls。Handle负责处理阻塞队列的call处理。然后处理的结果先自己发送,如果发送的完就结束此次请求,如果没法发送完就交给Responder去处理。Responder也是一个拥有Selector的线程,只负责处理写时间。

个人实现

  • 保留服务端基本架构
  • 移除Responder,让Handle线程之间发生所以数据
  • 将客户端的Socket连接替换为SocketChanel,使用buffer和服务器传递数据
  • 移除原框架自带的安全验证等和hadoop集群有关的功能组件
  • 利用开源的protostuff框架替换原有的序列化和反序列化工具

待改进计划

  • 使用Log4j作为日志,便于调试和日志配置

bug

  • bug1 多次向服务器发送请求会服务器会阻塞,貌似是发生了死锁
    bug原因,客户端一次执行多个任务的时候发生,第二次不应该再发起连接,否则就会向服务端发起两次请求,这样就会把一个连接交给两个Reader处理
    解决方向:
    研究源码服务端是如何处理来自同一个客户端的两个连接的
    研究源码客户端是如何处理连续的连接的

解决方案:
最终发现并不是死锁的问题,而是每次先读取对象大小紧接着就读取对象,但是实际上中间会有延迟导致读取对象读到的数据为0,所以要做一个循环判断读取数据是否为0.

  • bug2 每次客户端断开连接,服务器就得到一个读事件
    解决方案:
    每次channel.read()方法返回值为为负数的时候就将channel关闭
  • bug3 当某线程的一个空集合被放到锁空间进行循环判断的时候,其他线程是没有机会往空集合里添加数据的,所以如果集合为空就调用wait()让线程阻塞,其他线程添加完数据后再唤醒该线程。