分享在实现一个MapReduce调度器后遇到一些问题的解决过程
将5个WordCount作业通过example中的main函数提交后,没有使用响应的调度器调度。
问题:通过日志发现,5个WordCount作业并没有加入到map队列当中,队列为空,且tasktracker传回的map
任务个数始终为0,调查一下原因。
猜测原因1:hadoop默认提交作业到默认队列,如果要自定义队列,则需要配置。目前没有对map和reduce队列进行配置,因此作业没有提交到其中。(不是这样)
解决:
根本原因在于由于初始化作业时未获取到jobTracker的配置,默认为local,因此使用了localJobRunner类,而非JobTracker类,导致没有JobTrakcer和调度器等类的日志输出。
解决:尝试更换JobTracker配置的端口号。还是获取不到。
找到原因:WordCount作业的配置只使用了默认的配置,没有加载core-site,hdfs-site和mapred-site三个配置文件,导致JobTracker的配置不生效。
解决:将三个配置文件加入到配置对象中,运行正常。
新问题:在从map队列中remove元素时,作为键的JobSchedulingInfo对象在比较时为null,经过日志调试发现,键传入remove函数的参数并不是null,因此尝试调试队列中key的内容。
找到原因:并非JobSchedulingInfo对象为空而是该对象的newPriority字段(自定义的新优先级对象)为null。在JobSchedulingInfo对象加入队列时该字段是经过初始化的,那么就是因为oldJobSchedulingInfo对象中该字段为null导致。
解决:在status对象中添加newPriority即可。
新问题:assignTasks方法中有null错误,且map队列的大小一直在增加。
找到原因:因为在JobSchedulingInfo的compare方法中,比较了jobid和start time的同时也比较了newPriority,比较方法在查找过程中也在用。因此,在删除过程中由于newPriority的干扰一直找不到对应的对象。
首先仔细研究TreeMap的 getEntryUsingComparator(Object key)方法:
http://www.cnblogs.com/hzmark/archive/2013/01/02/TreeMap-Base.html
1 final Entry<K,V> getEntryUsingComparator(Object key) { 2 K k = (K) key; 3 // 获取比较器 4 Comparator<? super K> cpr = comparator; 5 // 其实在调用此方法的get(Object key)中已经对比较器为null的情况进行判断,这里是防御性的判断 6 if (cpr != null) { 7 // 获取根节点 8 Entry<K,V> p = root; 9 // 遍历树 10 while (p != null) { 11 // 获取key和当前节点的key的比较结果 12 int cmp = cpr.compare(k, p.key); 13 // 查找的key值较小 14 if (cmp < 0) 15 // p“移动”到左孩子 16 p = p.left; 17 // 查找的key值较大 18 else if (cmp > 0) 19 // p“移动”到右节点 20 p = p.right; 21 // key值相等 22 else 23 // 返回找到的节点 24 return p; 25 } 26 } 27 // 没找到key值对应的节点,返回null 28 return null; 29 }
有代码可见,remove在调用 getEntryUsingComparator(Object key)时使用了比较器的compare方法,由于map的实现是一个树结构,因此需要频繁的比较操作,因此compare的定义会影响remove的执行。
奇哉怪也!!!
remove方法竟然不调用compare方法!
调用了其实,只是日志没打印。
找到原因:在将job加入map队列时使用了newPriority的构造器,其中使用作业执行信息重新计算优先级,而开始时这个值被记为0,这与在JobInProgress对象中保存的初始值(MAX_VALUE)不同,导致优先级比较失败,在map中找不到scheduling info。
解决:尝试在构造器中判断如果是第一次执行,则置为MAX_VALUE。
针对map和reduce队列设置不同的优先级字段,比较时使用各自的优先级。初始化时作业类型为0。在删除作业后,将删除的作业对象的优先级更新,以反映到jobTracker的job列表中,保证下一次task在获取对应job时信息的正确性,否则会导致下一次查找失败。目前双队列机制工作正常。
下一步的工作是保证优先级算法的正确性(尤其是reduce队列)。