3.1 ConnectionManager
BlockManager还创建了ConnectionManager类,ConnectionManager类由端口,SparkConf,以及SecurityManager构成,它涉及到了几个重要的数据结构或者说类
ConnectionManagerId:由主机host和端口port构成;
ConnectionId:由ConnectionManagerId,唯一是被connection的Id号构成;
SendingConnection:由套接字地址,选择器连接;
Connection:由套接字通道,选择器,ConnectionManagerId,ConnectionId构成;
个人认为ConnectionManager的作用就在于连接从节点上的executor,然后在executor间进行数据传输以及读写,大致思路如下:
选择器--->从节点之间(更具体点说应该是executor)的通道---->选择键(SelectionKey)----->发送连接(SendingConnection),这样完成了从节点(或者说executor)间进行数据传输的通道,之后就可以进行相应的操作了
创建信息,读写,连接的执行线程,之后进行信息传送,读写以及连接操作
以写操作为例
private val writeRunnableStarted: HashSet[SelectionKey] = new HashSet[SelectionKey]()//创建选择键的set集
private def triggerWrite(key: SelectionKey) {//触发写操作
val conn = connectionsByKey.getOrElse(key, null)//通过选择键进行连接,连接的过程就是通过选择器来选择套接字通道,返回一个Connection对象
if (conn == null) return
writeRunnableStarted.synchronized {
if (conn.changeInterestForWrite()) conn.unregisterInterest()//判断是否需要注册SelectorKey的interest操作集
if (writeRunnableStarted.contains(key)) {
return
}
writeRunnableStarted += key//将该选择键加入到写开始选择键的set集中
}
handleReadWriteExecutor.execute(new Runnable {//执行读写线程
override def run() {
var register: Boolean = false
try {
register = conn.write()//判断能否进行写操作
} finally {
writeRunnableStarted.synchronized {
writeRunnableStarted -= key//发生异常,将该选择键从开始选择键的set集中删除
val needReregister = register || conn.resetForceReregister()
if (needReregister && conn.changeInterestForWrite()) {
conn.registerInterest()//重新开始尝试新一轮的写操作,也就是重置选择键的的interest集
}
}
}
}
} )
}
读操作类似,此外还有其他的一些方法,如处理客户端的认证问题,处理消息等等,因为代码略长,所以在此就不详细介绍,总之知道连接是通过通道,套接字(可以联想到我们上网浏览网页时发送HTTP请求)以及选择器完成,因此需要相应的这些数据结构,接着就可以理解ConnectionManager类的其他方法了。
BlockManager有MemoryStore,DiskStore,TachyonStore这三种存储数据的方式,调用他们的putValues(),tryToPut(),getValues()方法存放或者取数据
以MemoryStore的tryToPut()为例
首先判断要存的块的大小是否大于现有的空闲容量,若大于,则直接存于硬盘,否则->判断是否能从已经存于内存中的block块中空出内存来存放该block,若不能,则直接存与磁盘,否则->首先将空出的来的那些块存于磁盘,若空出来的块不支持磁盘存取,则仍然存于内存,否则,存于磁盘->最后再将该块存于内存
未完待续。。。