首先通过一张spark的架构图来了解worker在spark中的作用和地位:
worker所起的作用有以下几个:
1. 接受master的指令,启动或者杀掉executor
2. 接受master的指令,启动或者杀掉driver
3. 报告executor/driver的状态到master
4. 心跳到master,心跳超时则master认为worker已经挂了不能工作了
5. 向gui报告worker的状态
说白了,worker就是整个集群真正干活的。首先看一下worker重要的数据结构:
这些hash map存储了名字和实体时间的对应关系,方便通过名字直接找到实体进行调用。
看一下如何启动executor:
1行到3行是验证该命令是否发自一个合法的master。7到10行定义了一个executorrunner,实际上系统并没有一个类叫做executor,我们所说的executor实际上是由executorrunner实现的,这个名字起得也比较贴切。11行将新建的executor放到上面提到的hash map中。然后12行启动这个executor。13行和14行将现在已经使用的core和memory进行的统计。15到17行实际上是向master报告executor的状态。这里需要加锁。
如果在这过程中有异常抛出,那么需要check是否是executor已经加到hash map中,如果有则首先停止它,然后从hash map中删除它。并且向master report executor是failed的。master会重新启动新的executor。
接下来看一下driver的hash map的使用,通过killdriver:
这个killdirver的命令实际上由master发出的,而master实际上接收了client的kill driver的命令。这个也可以看出scala语言的简洁性。