Hadoop学习杂记(三)

分享在实现一个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队列)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章