hadoop1.0.4;
昨天写了一篇blog,是关于获取hadoop集群任务运行信息的例子,仿照50030界面实现。但是昨天遇到一个问题,就是当集群是第一次启动的时候,获得不了JobID,然后就拼凑不了JobID了,这样对后面的程序会有影响,所以想获得集群的第一个JobID,看到这个JobID是由“job_”+JobTracker启动时间+“_0001”得到的,所以获得JobTracker的启动时间就是最终的任务了,昨天找了好久,但是还是没有找到。
今天忽然想到了一种思路:既然hadoop提交任务会获得JobID,那么我去看hadoop任务提交的源码不就可以了。
最后追到JobTracker的代码里面就有获得启动时间的代码,那么就获得JobTracker吧,new JobTracker(jobConf),额,但是JobTracker构造方法是受保护的,获取不到,好吧。然后我就在那个包下面写了一个类来继承这个JobTracker,提升为public,如下:
package org.apache.hadoop.mapred; import java.io.IOException; /** * get the jobtracker identifier * @author fansy * */ public class JobTrackerChild extends JobTracker { /** * set the configuration * get the jobtracker start time * @param conf * @throws IOException * @throws InterruptedException */ public JobTrackerChild(JobConf conf) throws IOException, InterruptedException { super(conf); // TODO Auto-generated constructor stub } public String getTheTrackerIdentifier(){ return getTrackerIdentifier(); } }然后,测试代码:
package hadoop; import java.io.IOException; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.mapred.JobConf; import org.apache.hadoop.mapred.JobTrackerChild; public class GetJobId { /** * @param args * @throws IOException * @throws InterruptedException * @throws ClassNotFoundException */ public static void main(String[] args) throws IOException, ClassNotFoundException, InterruptedException { Configuration conf=new Configuration(); conf.set("mapred.job.tracker", "ubuntu:9001"); JobConf jobConf=new JobConf(conf); String identifier=new JobTrackerChild(jobConf).getTheTrackerIdentifier(); System.out.println(identifier); } }额,结果报了这样一个错误:
13/12/19 21:30:47 INFO delegation.AbstractDelegationTokenSecretManager: Updating the current master key for generating delegation tokens 13/12/19 21:30:47 INFO delegation.AbstractDelegationTokenSecretManager: Starting expired delegation token remover thread, tokenRemoverScanInterval=60 min(s) 13/12/19 21:30:47 INFO delegation.AbstractDelegationTokenSecretManager: Updating the current master key for generating delegation tokens 13/12/19 21:30:47 INFO mapred.JobTracker: Scheduler configured with (memSizeForMapSlotOnJT, memSizeForReduceSlotOnJT, limitMaxMemForMapTasks, limitMaxMemForReduceTasks) (-1, -1, -1, -1) 13/12/19 21:30:47 INFO util.HostsFileReader: Refreshing hosts (include/exclude) list 13/12/19 21:30:47 INFO mapred.JobTracker: Starting jobtracker with owner as Administrator Exception in thread "main" java.net.BindException: Problem binding to ubuntu/192.168.128.130:9001 : Cannot assign requested address: bind at org.apache.hadoop.ipc.Server.bind(Server.java:227) at org.apache.hadoop.ipc.Server$Listener.<init>(Server.java:301) at org.apache.hadoop.ipc.Server.<init>(Server.java:1483) at org.apache.hadoop.ipc.RPC$Server.<init>(RPC.java:546) at org.apache.hadoop.ipc.RPC.getServer(RPC.java:506) at org.apache.hadoop.mapred.JobTracker.<init>(JobTracker.java:2307) at org.apache.hadoop.mapred.JobTracker.<init>(JobTracker.java:2192) at org.apache.hadoop.mapred.JobTracker.<init>(JobTracker.java:2186) at org.apache.hadoop.mapred.JobTracker.<init>(JobTracker.java:2167) at org.apache.hadoop.mapred.JobTrackerChild.<init>(JobTrackerChild.java:20) at hadoop.GetJobId.main(GetJobId.java:22) Caused by: java.net.BindException: Cannot assign requested address: bind at sun.nio.ch.Net.bind0(Native Method) at sun.nio.ch.Net.bind(Net.java:444) at sun.nio.ch.Net.bind(Net.java:436) at sun.nio.ch.ServerSocketChannelImpl.bind(ServerSocketChannelImpl.java:214) at sun.nio.ch.ServerSocketAdaptor.bind(ServerSocketAdaptor.java:74) at org.apache.hadoop.ipc.Server.bind(Server.java:225) ... 10 more感觉是这个地址已经被另外一个用户(ubuntu上面的集群我是使用mahout用户启动的)启动了,所以我在myeclipse里面使用Administrator用户再新建一个JobTracker就会报错了(默认myeclipse发送的都是以Administrator用户来的或者说是win7登录用户)。
额,其实等它报错后,我才发现我想错了,不应该新建JobTracker的,(新建JobTrackerChild的时候就会新建一个JobTracker的),而是应该直接获取当前JobTracker的identifier属性的才对。
晕,居然想错了。然后网上又找,找到了一篇11年的文章:http://richardj.iteye.com/blog/1098244,这里说可以试试JobInProgress。
不过我没有试JobInProgress,因为打开JobInProgress看了下,然后又稍微试了下,感觉不行,然后就没继续试了。然而,我在那篇文章还是得到了一点启发:修改源码。其实我刚开始新建了一个JobTrackerChild也算是修改了源码吧,但是没有修改的那么明显。
怎么修改呢?看JobTracker的2485行,原来是这样的:
private static String generateNewIdentifier() { return getDateFormat().format(new Date()); }我改为了这样:
private static String generateNewIdentifier(JobConf conf) { String startTime=getDateFormat().format(new Date()); writeString(startTime,conf); return startTime; }其中的writeString就是把startTime写入文件,方法如下:
/** * write to local file the start time * @param value */ private static void writeString(String value,JobConf conf) { LOG.info("***********************************prepare to wirte to file with value:"+value); Path path=new Path("/private/jobtracker/starttime"); FileSystem fs; FSDataOutputStream out=null; try { fs = FileSystem.get(path.toUri(),conf); out = fs.create(path); out.writeUTF(value); } catch(Exception e){ LOG.info("********************************:"+e.getMessage()); }finally { Closeables.closeQuietly(out); } }针对上面的改法做如下的说明:
1. 传入了JobConf对象,因为JobTracker中的conf(其实就是JobConf对象)是非static的,但是generateNewIdentifier方法是static的,所以一定要new一个实例,但是new一个JobTracker实例违反获取当前JobTracker的初衷,所以采用传入JobConf对象。这里需要注意把调用generateNewIdentifier的方法全部都加上JobConf参数;包括293、2484、2165~2179之间的代码部分;
2. 为什么要传入一个JobConf对象呢?因为在writeString中需要使用JobConf对象获得FileSystem对象,然后写入数据。
编译后,替换hadoop-core-1.0.4.jar包,替换的文件如下:
重新启动hadoop集群,在hdfs文件系统上面查看/private/jobtracker/starttime文件,发现没有这个文件;那就说明没有进行文件信息写入。(那个文件目录是固定在代码中写死的)
然后我就开始怀疑有没有改到源码了,或者源码启动JobTracker是从这个入口进入的么?没办法,看有没有log信息吧,发现可以直接使用LOG.info()打印信息,好吧,用这个来看有没有改动吧。(修改的源码最后的样子就是上面的代码)
编译、替换、重启,好吧还没有那个文件,额,死心吧(其实,刚开始看到11年的那个文章,上面也说写入文件什么的都没有用,我就想小样儿,应该是写入hdfs文件吧,你应该是写入本地了吧,肯定不行的啦,结果自己试了试,居然还真写不了hdfs,哎。。。)
直接查看log信息吧,如下:
结果。。。
结果你都看到了,额,的确是写入错误,因为是safemode,所以这里会有问题,哎。
那就想要不要在safemode关闭后再写入呢?等等。。。
其实,这里已经很明显了,可以在log中记录这个信息,然后去搜索log,找到JobTracker启动的参数(话说回来,其实log里面已经包括JobTracker启动参数了),最简单的做法,如果你不想使用log本来的信息,比如希望像上面图片那样直接一个匹配就可以找到值(上面图片匹配的字符串可以认为是”***********************************prepare
to wirte to file with value:“)。这样就不用解析log了,直接匹配自己固定写的字符串即可(其实也算是简单的解析了)。
额,好吧,又是一整晚。哎,又是连着盯着屏幕几个钟头,要近视的节奏。。。
如果您觉得lz的blog或者资源还ok的话,可以选择给lz投一票,多谢。(投票地址:http://vote.blog.csdn.net/blogstaritem/blogstar2013/fansy1990 )
分享,成长,快乐
转载请注明blog地址:http://blog.csdn.net/fansy1990