java web调用mapreduce算法-Day2&4(更新)

本文记录了在Hadoop集群部署过程中遇到的各种问题及解决方案,包括Tomcat启动失败、MySQL写文件错误、MapReduce任务执行缓慢等常见故障。通过调整配置、优化代码和重启服务等手段最终实现了系统的稳定运行。

 哈哈 在这千钧一发的时刻,居然好用了~时刻:22:37

1.第一个问题,由于昨天启动Tomcat次数过多,有很多日志留在/tmp目录下,可能还有别的原因,导致今天一来启动Tomcat就不行了,因为磁盘空间不足,后来师兄删了日志,并且告诉我记得自己删日志,还挪了11G磁盘空间给这个分区,这样就顺畅了~

2.MySQL报错:MySQL: Can't create/write to file '/tmp/#sql_3c6_0.MYI' (Errcode: 2)这种

https://stackoverflow.com/questions/11997012/mysql-cant-create-write-to-file-tmp-sql-3c6-0-myi-errcode-2-what-does

也是在stackoverflow的这个帖子下找到方法,那就是,重启MySQL哈哈,其中一个人说自己每个月遇到两三次这种情况,每次重启一下就好了,我就又麻烦师兄帮忙重启下MySQL,果然,OK了,原因大概是师兄删tmp目录的时候把什么东西也删掉了吧

3.然后就是昨天的查询慢的问题了,先说今天试MySQL查询,在小表上第一条是慢的,第二条之后就稳定了,但是在大数据集上,1G+就还是10min+今天,就先不管它了,昨天比较加上框架在集群上跑就卡在map11%了,今天调好了一跑还是卡在那;同时昨天和今天我都注意到一个问题,那就是启动的是localjobrunner,job的名称也是job_local***,那就说明这是本地模式啊,很可能因为这个所以才特别慢并且还占了很多磁盘空间,之后就baiduHadoop集群模式启动,我的代码通过调用类的main方法,就相当于eclipse直接运行main函数提交任务到Hadoop集群是一样的,一般我们使用命令行hadoop jar [jar-path][mainclass-name][input][output],这个命令行实现的就是将jar包提交到集群的各个节点上,所以用eclipse提交也必须完成这个功能,让集群需要知道这四个参数(命令行提供的),我的main函数代码如下:

Configuration conf = new Configuration();
conf.set("mapreduce.job.jar","/home/user/***.jar");  //change
conf.set("fs.defaultFS", "hdfs://master:9000/");          //change
conf.set("mapreduce.framework.name", "yarn");               //change
conf.set("yarn.resourcemanager.hostname", "master.cluster"); 
Job job = Job.getInstance(conf, "springboot");
job.setJarByClass(WordCount.class); 
 job.setMapperClass(TokenizerMapper.class);
 job.setReducerClass(IntSumReducer.class);
 job.setOutputKeyClass(LongWritable.class);
 job.setOutputValueClass(Text.class);
 FileInputFormat.addInputPath(job, new Path(args[0]));
 FileOutputFormat.setOutputPath(job, new Path(args[1]));
 job.waitForCompletion(true);


mapred.jar就是命令行提供的jar-path参数了,放在本地的那种;

fs.defaultFS这个就是HDFS的配置,想操作HDFS也要提供的,网上很多讲解了;

mapreduce.framework.name写死的,yarn模式就是集群模式;

yarn.resourcemanager.hostname也是在配置文件里的,去集群的配置文件看一看就好了;

关于命令行提供的[input][output]两个参数,是我调用这个main时指定的;[mainclass-name]这个参数,是我们打jar包时指定的(用eclipse的export打包,不是maven那种哦~)。



然鹅,和网上贴的代码不一样的就是,去掉了setjarbyclass,弄了一天终于跑起来了。因为我把springboot打成一个jar包ssh远程登录集群运行的工程,mapreduce.job.jar的路径是本地路径,所以我这里面涉及了两个jar!我实验了多种觉得mapreduce.job.jar参数应该是不能用jar包里的相对路径,所以jar不用打在工程里面(之前报ClassNotFound我想可能是运行的是jar就不能引用外部jar的class了?所以尝试把要跑的jar打进maven工程里,为了maven添加进本地jar包,我也卡了大半天,解决思路是把jar包install进本地仓库,然后dependency依赖加上就行,scope写runtime就打进去了),放在本地就行。所以我理解可能是由于setjarbyclass在conf设置mapreduce.job.jar后面,把之前的覆盖了,而mapreduce.job.jar才是我们要跑的jar,然后我就验证了一下我的想法,终于不报ClassNotFound了(幸运之神眷顾我啊……毕竟我也准备好了还有其它可能一个一个试呢,看见这“激动人心”的结果,真是幸运~)。(但是跑的很慢,卡在了数据库查询上,在本地模式跑也遇到过这种情况反正,重启大法反正就好了,可能文件什么的太多了又没空间了??)现在能跑起来的“环境”是:要运行的jar有setjarbyclass,springboot中调用的main里去掉。

http://www.aboutyun.com/thread-9366-1-1.html 讲的比较深,说是setjarbyclass方法就是找到class所属的jar以后赋值给mapreduce.job.jar,于是我就想到可能被覆盖了的问题。

因为我在本地运行main里和jar的main里都有setjarbyclass,但是可以运行并且结果正确,所以觉得setjarbyclass是问题根源的可能性很低,只是顺手试一试,没想到居然真的跟它有关系……

我想应该是放在集群上的时候main本身就在我打成的jar里,而且还有一个真正运行的jar,就两个了,而本地只有一个,毕竟本地的main在eclipse里运行所以不会有误会/覆盖吧,所以集群上的main才要去掉setjarbyclass。

因为我是远程ssh操作集群,所以把Mapreduce算法的jar包打好,放到集群我的用户目录下,不用上传到HDFS上啦,然后把我的springboot工程用maven build好出jar包,放到集群上,java -DServer.port=8090 -jar ***.jar启动,试着访问以下该方法,不仅Mapreduce成功,操作HDFS成功,数据也返回到浏览器上了~搞定~


说两个昨天落下忘讲了的小问题:

1.Java web调用Mapreduce的时候,main里面写的是System.exit(job.waitForcompletion(true)),这就导致什么呢,导致Mapreduce运行完JVM就关闭了,然后会导致Tomcat重启啥的而且重启会失败,具体我忘了,所以去掉System.exit就好~

2.“cd /”命令,师兄今天来我这帮我解决问题,我才知道还有这个目录呢,我之前以为只有我的主目录也就是“cd ~”访问到的那个,“cd /”就是root目录了吧,很厉害,想Hadoop_home还有我要定时清理的/tmp都在下面了,厉害厉害。


贴个图片纪念我这一晚的……推理秀!






package myPageRank; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Mapper; import java.io.IOException; import java.util.StringTokenizer; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Reducer; import java.io.IOException; import java.util.ArrayList; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.IntWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapred.lib.ChainMapper; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; /** * @author tulie * @ceerte $(YEAR)-$(MONTH)-$(DAY)-$(TIME) */ /** * @author tulie * @ceerte $(YEAR)-$(MONTH)-$(DAY)-$(TIME) */ public class PRMapper extends Mapper<Object, Text, IntWritable, Text> { private IntWritable id; private String pr; private int count; private float average_pr; //重写map方法 public void map(Object key, Text value, Context context) { //构造一个用来解析 str 的 StringTokenizer 对象。java 默认的分隔符是空格("")、制表符(\t)、换行符(\n)、回车符(\r)。 StringTokenizer str = new StringTokenizer(value.toString()); //|1 6 2 4 5 if(str.hasMoreTokens())//返回是否还有分隔符 { id = new IntWritable(Integer.parseInt(str.nextToken()));//1 |6 2 4 5 }else{ return; } pr = str.nextToken();//返回从当前位置到下一个分隔符的字符串 1 6 |2 4 5 count = str.countTokens();//3 average_pr = Float.parseFloat(pr)/count; while(str.hasMoreTokens()) { try{ String nextId = str.nextToken();//1 6 2| 4 5 IntWritable linid = new IntWritable(Integer.parseInt(nextId)); //将网页向外链接的ID以“pr+得到贡献值”格式输出 Text avpr = new Text("pr" + average_pr); context.write(linid, avpr); // 将网页ID和PR值输出 Text ids = new Text("id" + nextId); context.write(id, ids); }catch(IOException e) { e.printStackTrace(); }catch (InterruptedException e) { e.printStackTrace(); } } } } /** * @author tulie * @ceerte $(YEAR)-$(MONTH)-$(DAY)-$(TIME) */ public class PRReducer extends Reducer<IntWritable, Text, IntWritable, Text> { //重写reduce方法 public void reduce(IntWritable key, Iterable<Text> values, Context context) { // 定义一个存储网页链接ID的队列 ArrayList<String> ids = new ArrayList<String>(); // 将所有的链接ID以String格式保存 String strid = " "; // 定义一个保存网页PR值的变量 float pr = 0; //遍历 System.out.println(key.get()); for(Text txt : values) { String str = txt.toString(); //判断value是贡献值还是向外部的链接 if (str.startsWith("pr")) { // 贡献值 pr += Float.parseFloat(str.substring(2)); System.out.println(pr); } else if (str.startsWith("id")) { // 链接id String id = str.substring(2); ids.add(id); } } pr = 0.85f*pr + 0.15f; // 得到所有链接ID的String形式 for (int i = 0; i < ids.size(); i++) { strid += ids.get(i) + " "; } // 组合pr+lianjie成原文件的格式类型 String strpr = String.format("%.5f", pr); String result = strpr + strid; try { context.write(key, new Text(result)); } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } } } (为我修改错误给出完整代码)
最新发布
10-22
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值