- 浏览: 2183965 次
- 性别:
- 来自: 北京
文章分类
- 全部博客 (682)
- 软件思想 (7)
- Lucene(修真篇) (17)
- Lucene(仙界篇) (20)
- Lucene(神界篇) (11)
- Solr (48)
- Hadoop (77)
- Spark (38)
- Hbase (26)
- Hive (19)
- Pig (25)
- ELK (64)
- Zookeeper (12)
- JAVA (119)
- Linux (59)
- 多线程 (8)
- Nutch (5)
- JAVA EE (21)
- Oracle (7)
- Python (32)
- Xml (5)
- Gson (1)
- Cygwin (1)
- JavaScript (4)
- MySQL (9)
- Lucene/Solr(转) (5)
- 缓存 (2)
- Github/Git (1)
- 开源爬虫 (1)
- Hadoop运维 (7)
- shell命令 (9)
- 生活感悟 (42)
- shell编程 (23)
- Scala (11)
- MongoDB (3)
- docker (2)
- Nodejs (3)
- Neo4j (5)
- storm (3)
- opencv (1)
最新评论
-
qindongliang1922:
粟谷_sugu 写道不太理解“分词字段存储docvalue是没 ...
浅谈Lucene中的DocValues -
粟谷_sugu:
不太理解“分词字段存储docvalue是没有意义的”,这句话, ...
浅谈Lucene中的DocValues -
yin_bp:
高性能elasticsearch ORM开发库使用文档http ...
为什么说Elasticsearch搜索是近实时的? -
hackWang:
请问博主,有用solr做电商的搜索项目?
Solr中Group和Facet的用法 -
章司nana:
遇到的问题同楼上 为什么会返回null
Lucene4.3开发之第八步之渡劫初期(八)
记录下,散仙今天的工作以及遇到的问题和解决方案,俗话说,好记性不如烂笔头,写出来文章,供大家参考,学习和点评,进步,才是王道 ,废话不多说,下面切入主题:
先介绍下需求:
散仙要处理多个类似表的txt数据,当然只有值,列名什么的全部在xml里配置了,然后加工这些每个表的每一行数据,生成特定的格式基于ASCII码1和ASCII码2作为分隔符的一行数据,ASCII2作为字段名和字段值的分隔符,ASCII1作为字段和字段之间的分隔符,每解析一个txt文件时,都要获取文件名,然后与xml中的schema信息映射并找到对应位置的值,它的列名,前提是,这些的txt的内容位置,是固定的,然后我们知道它每一行属于哪个表结构的映射,因为这些映射信息是提前配置在xml中的,如下图:
当然类似这样的结构有20个左右的表文件,到时候,我们的数据方,会给我们提供这些txt文件,然后散仙需要加工成特定的格式,然后写入HDFS,由我们的索引系统使用MapReduce批量建索引使用。
本来想直接用java写个单机程序,串行处理,然后写入HDFS,后来一想假如数据量比较大,串行程序还得改成多线程并行执行,这样改来改去,倒不如直接使用MapReduce来的方便
ok,说干就干,测试环境已经有一套CDH5.3的hadoop2.5集群,直接就在eclipse进行开发和MapReduce程序的调试,反正也好久也没手写MapReduce了,前段时间,一直在用Apache Pig分析数据,这次处理的逻辑也不复杂,就再写下练练手 , CDH的集群在远程的服务器上,散仙本机的hadoop是Apache Hadoop2.2的版本,在使用eclipse进行开发时,也没来得及换版本,理论上最好各个版本,不同发行版,之间对应起来开发比较好,这样一般不会存在兼容性问题,但散仙这次就懒的换了,因为CDH5.x之后的版本,是基于社区版的Apache Hadoop2.2之上改造的,接口应该大部分都一致,当然这只是散仙猜想的。
(1)首先,散仙要搞定的事,就是解析xml了,在程序启动之前需要把xml解析,加载到一个Map中,这样在处理每种txt时,会根据文件名来去Map中找到对应的schma信息,解析xml,散仙直接使用的jsoup,具体为啥,请点击散仙这篇
http://qindongliang.iteye.com/blog/2162519文章,在这期间遇到了一个比较蛋疼的问题,简直是一个bug,最早散仙定义的xml是每个表,一个table标签,然后它下面有各个property的映射定义,但是在用jsoup的cssQuery语法解析时,发现总是解析不出来东西,按照以前的做法,是没任何问题的,这次简直是开玩笑了,后来就是各种搜索,测试,最后才发现,将table标签,换成其他的任何标签都无任何问题,具体原因,散仙还没来得及细看jsoup的源码,猜测table标签应该是一个关键词什么的标签,在解析时会和html的table冲突,所以在xml解析中失效了,花了接近2个小时,求证,检验,终于搞定了这个小bug。
(2)搞定了这个问题,散仙就开始开发调试MapReduce版的处理程序,这下面临的又一个问题,就是如何使用Jsoup解析存放在HDFS上的xml文件,有过Hadoop编程经验的人,应该都知道,HDFS是一套分布式的文件系统,与我们本地的磁盘的存储方式是不一样的,比如你在正常的JAVA程序上解析在C:\file\t.tx或者在linux上/home/user/t.txt,所编写的程序在Hadoop上是无法使用的,你得使用Hadoop提供的编程接口获取它的文件信息,然后转成字符串之后,再给jsoup解析。
(3)ok,第二个问题搞定之后,你得编写你的MR程序,处理对应的txt文本,而且保证不同的txt里面的数据格式,所获取的scheaml是正确的,所以在map方法里,你要获取当然处理文件的路径,然后做相应判断,在做对应处理。
(4)很好,第三个问题搞定之后,你的MR的程序,基本编写的差不多了,下一步就改考虑如何提交到Hadoop的集群上,来调试程序了,由于散仙是在Win上的eclipse开发的,所以这一步可能遇到的问题会很多,而且加上,hadoop的版本不一致与发行商也不一致,出问题也纯属正常。
这里多写一点,一般建议大家不要在win上调试hadoop程序,这里的坑非常多,如果可以,还是建议大家在linux上直接玩,下面说下,散仙今天又踩的坑,关于在windows上调试eclipse开发, 运行Yarn的MR程序,散仙以前也记录了文章,感兴趣者,可以点击这个链接
http://qindongliang.iteye.com/blog/2078452地址。
(5)提交前,是需要使用ant或maven或者java自带的导出工具,将项目打成一个jar包提交的,这一点大家需要注意下,最后测试得出,Apache的hadoop2.2编写的MR程序,是可以直接向CDH Hadoop2.5提交作业的,但是由于hadoop2.5中,使用google的guice作为了一个内嵌的MVC轻量级的框架,所以在windows上打包提交时,需要引入额外的guice的几个包,截图如下:
上面几步搞定后,打包整个项目,然后运行成功,过程如下:
最后附上核心代码,以作备忘:
(1)Map Only作业的代码:
使用解析HDFS上xml文件的代码:
项目结构如下图:
Ant的打包脚本如下:
至此,我们以及完成了,这个小项目的开发,最终回归当生产环境上,我们是需要打成jar包,在linux上定时执行的,直接使用linux环境来开发调试hadoop,遇到的问题会更少,虽然不推荐使用win直接开发hadoop程序,但是了解一些基本的方法和技巧,对我们来说也是一件不错的事情。
最后欢迎大家扫码关注微信公众号:我是攻城师(woshigcs)
本公众号的内容是有关搜索和大数据技术和互联网等方面内容的分享,也是一个温馨的技术互动交流的小家园,有什么问题随时都可以留言,欢迎大家来访!
先介绍下需求:
散仙要处理多个类似表的txt数据,当然只有值,列名什么的全部在xml里配置了,然后加工这些每个表的每一行数据,生成特定的格式基于ASCII码1和ASCII码2作为分隔符的一行数据,ASCII2作为字段名和字段值的分隔符,ASCII1作为字段和字段之间的分隔符,每解析一个txt文件时,都要获取文件名,然后与xml中的schema信息映射并找到对应位置的值,它的列名,前提是,这些的txt的内容位置,是固定的,然后我们知道它每一行属于哪个表结构的映射,因为这些映射信息是提前配置在xml中的,如下图:
当然类似这样的结构有20个左右的表文件,到时候,我们的数据方,会给我们提供这些txt文件,然后散仙需要加工成特定的格式,然后写入HDFS,由我们的索引系统使用MapReduce批量建索引使用。
本来想直接用java写个单机程序,串行处理,然后写入HDFS,后来一想假如数据量比较大,串行程序还得改成多线程并行执行,这样改来改去,倒不如直接使用MapReduce来的方便
ok,说干就干,测试环境已经有一套CDH5.3的hadoop2.5集群,直接就在eclipse进行开发和MapReduce程序的调试,反正也好久也没手写MapReduce了,前段时间,一直在用Apache Pig分析数据,这次处理的逻辑也不复杂,就再写下练练手 , CDH的集群在远程的服务器上,散仙本机的hadoop是Apache Hadoop2.2的版本,在使用eclipse进行开发时,也没来得及换版本,理论上最好各个版本,不同发行版,之间对应起来开发比较好,这样一般不会存在兼容性问题,但散仙这次就懒的换了,因为CDH5.x之后的版本,是基于社区版的Apache Hadoop2.2之上改造的,接口应该大部分都一致,当然这只是散仙猜想的。
(1)首先,散仙要搞定的事,就是解析xml了,在程序启动之前需要把xml解析,加载到一个Map中,这样在处理每种txt时,会根据文件名来去Map中找到对应的schma信息,解析xml,散仙直接使用的jsoup,具体为啥,请点击散仙这篇
http://qindongliang.iteye.com/blog/2162519文章,在这期间遇到了一个比较蛋疼的问题,简直是一个bug,最早散仙定义的xml是每个表,一个table标签,然后它下面有各个property的映射定义,但是在用jsoup的cssQuery语法解析时,发现总是解析不出来东西,按照以前的做法,是没任何问题的,这次简直是开玩笑了,后来就是各种搜索,测试,最后才发现,将table标签,换成其他的任何标签都无任何问题,具体原因,散仙还没来得及细看jsoup的源码,猜测table标签应该是一个关键词什么的标签,在解析时会和html的table冲突,所以在xml解析中失效了,花了接近2个小时,求证,检验,终于搞定了这个小bug。
(2)搞定了这个问题,散仙就开始开发调试MapReduce版的处理程序,这下面临的又一个问题,就是如何使用Jsoup解析存放在HDFS上的xml文件,有过Hadoop编程经验的人,应该都知道,HDFS是一套分布式的文件系统,与我们本地的磁盘的存储方式是不一样的,比如你在正常的JAVA程序上解析在C:\file\t.tx或者在linux上/home/user/t.txt,所编写的程序在Hadoop上是无法使用的,你得使用Hadoop提供的编程接口获取它的文件信息,然后转成字符串之后,再给jsoup解析。
(3)ok,第二个问题搞定之后,你得编写你的MR程序,处理对应的txt文本,而且保证不同的txt里面的数据格式,所获取的scheaml是正确的,所以在map方法里,你要获取当然处理文件的路径,然后做相应判断,在做对应处理。
(4)很好,第三个问题搞定之后,你的MR的程序,基本编写的差不多了,下一步就改考虑如何提交到Hadoop的集群上,来调试程序了,由于散仙是在Win上的eclipse开发的,所以这一步可能遇到的问题会很多,而且加上,hadoop的版本不一致与发行商也不一致,出问题也纯属正常。
这里多写一点,一般建议大家不要在win上调试hadoop程序,这里的坑非常多,如果可以,还是建议大家在linux上直接玩,下面说下,散仙今天又踩的坑,关于在windows上调试eclipse开发, 运行Yarn的MR程序,散仙以前也记录了文章,感兴趣者,可以点击这个链接
http://qindongliang.iteye.com/blog/2078452地址。
(5)提交前,是需要使用ant或maven或者java自带的导出工具,将项目打成一个jar包提交的,这一点大家需要注意下,最后测试得出,Apache的hadoop2.2编写的MR程序,是可以直接向CDH Hadoop2.5提交作业的,但是由于hadoop2.5中,使用google的guice作为了一个内嵌的MVC轻量级的框架,所以在windows上打包提交时,需要引入额外的guice的几个包,截图如下:
上面几步搞定后,打包整个项目,然后运行成功,过程如下:
输出路径存在,已删除! 2015-04-08 19:35:18,001 INFO [main] client.RMProxy (RMProxy.java:createRMProxy(56)) - Connecting to ResourceManager at /172.26.150.18:8032 2015-04-08 19:35:18,170 WARN [main] mapreduce.JobSubmitter (JobSubmitter.java:copyAndConfigureFiles(149)) - Hadoop command-line option parsing not performed. Implement the Tool interface and execute your application with ToolRunner to remedy this. 2015-04-08 19:35:21,156 INFO [main] input.FileInputFormat (FileInputFormat.java:listStatus(287)) - Total input paths to process : 2 2015-04-08 19:35:21,219 INFO [main] mapreduce.JobSubmitter (JobSubmitter.java:submitJobInternal(394)) - number of splits:2 2015-04-08 19:35:21,228 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - user.name is deprecated. Instead, use mapreduce.job.user.name 2015-04-08 19:35:21,228 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.jar is deprecated. Instead, use mapreduce.job.jar 2015-04-08 19:35:21,228 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - fs.default.name is deprecated. Instead, use fs.defaultFS 2015-04-08 19:35:21,229 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.reduce.tasks is deprecated. Instead, use mapreduce.job.reduces 2015-04-08 19:35:21,229 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.mapoutput.value.class is deprecated. Instead, use mapreduce.map.output.value.class 2015-04-08 19:35:21,230 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.map.class is deprecated. Instead, use mapreduce.job.map.class 2015-04-08 19:35:21,230 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.job.name is deprecated. Instead, use mapreduce.job.name 2015-04-08 19:35:21,230 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.inputformat.class is deprecated. Instead, use mapreduce.job.inputformat.class 2015-04-08 19:35:21,230 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.input.dir is deprecated. Instead, use mapreduce.input.fileinputformat.inputdir 2015-04-08 19:35:21,230 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.output.dir is deprecated. Instead, use mapreduce.output.fileoutputformat.outputdir 2015-04-08 19:35:21,230 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapreduce.outputformat.class is deprecated. Instead, use mapreduce.job.outputformat.class 2015-04-08 19:35:21,231 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.map.tasks is deprecated. Instead, use mapreduce.job.maps 2015-04-08 19:35:21,233 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.mapoutput.key.class is deprecated. Instead, use mapreduce.map.output.key.class 2015-04-08 19:35:21,233 INFO [main] Configuration.deprecation (Configuration.java:warnOnceIfDeprecated(840)) - mapred.working.dir is deprecated. Instead, use mapreduce.job.working.dir 2015-04-08 19:35:21,331 INFO [main] mapreduce.JobSubmitter (JobSubmitter.java:printTokens(477)) - Submitting tokens for job: job_1419419533357_5012 2015-04-08 19:35:21,481 INFO [main] impl.YarnClientImpl (YarnClientImpl.java:submitApplication(174)) - Submitted application application_1419419533357_5012 to ResourceManager at /172.21.50.108:8032 2015-04-08 19:35:21,506 INFO [main] mapreduce.Job (Job.java:submit(1272)) - The url to track the job: http://http://dnode1:8088/proxy/application_1419419533357_5012/ 2015-04-08 19:35:21,506 INFO [main] mapreduce.Job (Job.java:monitorAndPrintJob(1317)) - Running job: job_1419419533357_5012 2015-04-08 19:35:33,777 INFO [main] mapreduce.Job (Job.java:monitorAndPrintJob(1338)) - Job job_1419419533357_5012 running in uber mode : false 2015-04-08 19:35:33,779 INFO [main] mapreduce.Job (Job.java:monitorAndPrintJob(1345)) - map 0% reduce 0% 2015-04-08 19:35:43,885 INFO [main] mapreduce.Job (Job.java:monitorAndPrintJob(1345)) - map 100% reduce 0% 2015-04-08 19:35:43,902 INFO [main] mapreduce.Job (Job.java:monitorAndPrintJob(1356)) - Job job_1419419533357_5012 completed successfully 2015-04-08 19:35:44,011 INFO [main] mapreduce.Job (Job.java:monitorAndPrintJob(1363)) - Counters: 27 File System Counters FILE: Number of bytes read=0 FILE: Number of bytes written=166572 FILE: Number of read operations=0 FILE: Number of large read operations=0 FILE: Number of write operations=0 HDFS: Number of bytes read=47795 HDFS: Number of bytes written=594 HDFS: Number of read operations=12 HDFS: Number of large read operations=0 HDFS: Number of write operations=4 Job Counters Launched map tasks=2 Data-local map tasks=2 Total time spent by all maps in occupied slots (ms)=9617 Total time spent by all reduces in occupied slots (ms)=0 Map-Reduce Framework Map input records=11 Map output records=5 Input split bytes=252 Spilled Records=0 Failed Shuffles=0 Merged Map outputs=0 GC time elapsed (ms)=53 CPU time spent (ms)=2910 Physical memory (bytes) snapshot=327467008 Virtual memory (bytes) snapshot=1905754112 Total committed heap usage (bytes)=402653184 File Input Format Counters Bytes Read=541 File Output Format Counters Bytes Written=594 true
最后附上核心代码,以作备忘:
(1)Map Only作业的代码:
package com.dhgate.search.rate.convert; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FilenameFilter; import java.io.IOException; import java.util.Map; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.apache.hadoop.io.LongWritable; import org.apache.hadoop.io.NullWritable; import org.apache.hadoop.io.Text; import org.apache.hadoop.mapreduce.Job; import org.apache.hadoop.mapreduce.Mapper; import org.apache.hadoop.mapreduce.lib.input.FileInputFormat; import org.apache.hadoop.mapreduce.lib.input.FileSplit; import org.apache.hadoop.mapreduce.lib.input.TextInputFormat; import org.apache.hadoop.mapreduce.lib.output.FileOutputFormat; import org.apache.hadoop.mapreduce.lib.output.TextOutputFormat; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import com.dhgate.parse.xml.tools.HDFSParseXmlTools; import com.sun.xml.bind.v2.schemagen.xmlschema.Import; /** * 加工处理数据格式 * * @author qindongliang 2015年04月07日 * * **/ public class StoreConvert { //log4j记录 static Logger log=LoggerFactory.getLogger(StoreConvert.class); /** * 转换支持的格式 * * **/ private static class FormatMapper extends Mapper<LongWritable, Text, NullWritable, Text>{ @Override protected void map(LongWritable key, Text value,Context context)throws IOException, InterruptedException { String filename = ((FileSplit) context.getInputSplit()).getPath().getName().split("\\.")[0]; //System.out.println("文件名是: "+filename); //log.info("读取的文件名是: "+filename); String vs[]=value.toString().split(","); if(HDFSParseXmlTools.map.get(filename)!=null){ Map<String, String> m=HDFSParseXmlTools.map.get(filename); StringBuffer sb=new StringBuffer(); for(int i=0;i<vs.length;i++){ //字段\2值 if(i==vs.length-1){ sb.append(m.get(i+"")).append("\2").append(vs[i]); }else{ sb.append(m.get(i+"")).append("\2").append(vs[i]).append("\1"); } } context.write(NullWritable.get(), new Text(filename+" == "+sb.toString())); } } } public static void main(String[] args) throws Exception { // System.setProperty("HADOOP_USER_NAME", "root"); Configuration conf=new Configuration(); // getConf(conf); conf.set("mapreduce.job.jar", "searchrate.jar"); conf.set("fs.defaultFS","hdfs://172.21.50.108:8020"); conf.set("mapreduce.framework.name", "yarn"); conf.set("mapred.remote.os", "Linux"); conf.set("yarn.resourcemanager.scheduler.address", "172.21.50.108:8030"); conf.set("yarn.resourcemanager.address", "172.21.50.108:8032"); // System.exit(0); Job job=Job.getInstance(conf, "formatdata"); job.setJarByClass(StoreConvert.class); // System.out.println("模式: "+conf.get("mapreduce.jobtracker.address"));; job.setMapperClass(FormatMapper.class); job.setMapOutputKeyClass(Text.class); job.setMapOutputValueClass(Text.class); job.setInputFormatClass(TextInputFormat.class); job.setOutputFormatClass(TextOutputFormat.class); job.setNumReduceTasks(0);//Map Only作业 String path = "/tmp/qin/out"; FileSystem fs = FileSystem.get(conf); Path p = new Path(path); if (fs.exists(p)) { fs.delete(p, true); System.out.println("输出路径存在,已删除!"); } FileInputFormat.setInputPaths(job, "/tmp/qin/testfile/"); FileOutputFormat.setOutputPath(job, p); System.out.println(job.waitForCompletion(true)); } }
使用解析HDFS上xml文件的代码:
package com.dhgate.parse.xml.tools; import java.io.BufferedReader; import java.io.InputStreamReader; import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import org.apache.hadoop.conf.Configuration; import org.apache.hadoop.fs.FileSystem; import org.apache.hadoop.fs.Path; import org.jsoup.Jsoup; import org.jsoup.nodes.Document; import org.jsoup.nodes.Element; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * Created by qindongliang on 15-4-6. * 大数据交流群:415886155 */ public class HDFSParseXmlTools { private final static Logger log= LoggerFactory.getLogger(HDFSParseXmlTools.class); //存储元数据信息 public static Map<String, Map<String, String>> map=new HashMap<String, Map<String,String>>(); static Configuration conf=new Configuration(); static FileSystem fs=null; static{ log.info("初始化加载mapping.xml开始......."); try{ conf.set("fs.defaultFS","hdfs://172.21.50.108:8020/"); fs=FileSystem.get(conf);//获取conf对象 Path xml =new Path("/tmp/qin/mapping.xml");//读取HDFS的xml文件 BufferedReader br=new BufferedReader(new InputStreamReader(fs.open(xml)));//获取输入流 StringBuffer sb=new StringBuffer();//声明一个buffer对象用来存储xml文件内容 String line; line=br.readLine();//读取第一行 sb.append(line);//追加到StringBuffer中 while (line != null){ line=br.readLine();//循环读取 sb.append(line);//循环追加 } // System.out.println(sb.toString()); br.close();//释放资源 Document d=Jsoup.parse(sb.toString(),"UTF-8");//解析xml Set<String> set=new HashSet<String>();//排除,不需要解析的文件 List<Element> excludes=d.select("exclude"); for(Element ee:excludes){ set.add(ee.text().trim()); } List<Element> tables=d.select("type"); for(Element t:tables){ String num=t.attr("num"); String name=t.attr("name"); String indexname=t.attr("indexname"); if(set.contains(name)){ log.info("跳过的表名:"+name); continue; } // System.out.println(" 序号: "+num+" 表名: "+name+" 索引名: "+indexname); Map<String, String> data=new TreeMap<String, String>(); for(Element s:t.select("map")){ // System.out.println("----------------------"+s.attr("pos")+" "+s.attr("field")+" "+s.attr("")); String pos=s.attr("pos");//位置信息 String field=s.attr("field");//索引字段名 data.put(pos, field); } map.put(name, data);//将此表名对应的映射信息存储到map里 } }catch(Exception e){ //e.printStackTrace(); log.error("加载映射文件异常!",e); } } public static void parseXml()throws Exception{ } public static void main(String[] args) throws Exception{ System.out.println(); for(Entry<String, Map<String, String>> m:map.entrySet()){ System.out.println("表名:"+m.getKey()); // for(Entry<String, String> me:m.getValue().entrySet()){ // System.out.println(me.getKey()+" "+me.getValue()); // } // System.out.println("=================================================="); } } }
项目结构如下图:
Ant的打包脚本如下:
<project name="${component.name}" basedir="." default="jar"> <property environment="env"/> <!-- <property name="hadoop.home" value="${env.HADOOP_HOME}"/> --> <property name="hadoop.home" value="E:/hadooplib"/> <!-- 指定jar包的名字 --> <property name="jar.name" value="searchrate.jar"/> <path id="project.classpath"> <fileset dir="lib"> <include name="*.jar" /> </fileset> <fileset dir="${hadoop.home}"> <include name="**/*.jar" /> </fileset> </path> <target name="clean" > <delete dir="bin" failonerror="false" /> <mkdir dir="bin"/> </target> <target name="build" depends="clean"> <echo message="${ant.project.name}: ${ant.file}"/> <javac destdir="bin" encoding="utf-8" debug="true" includeantruntime="false" debuglevel="lines,vars,source"> <src path="src"/> <exclude name="**/.svn" /> <classpath refid="project.classpath"/> </javac> <copy todir="bin"> <fileset dir="src"> <include name="*config*"/> </fileset> </copy> </target> <target name="jar" depends="build"> <copy todir="bin/lib"> <fileset dir="lib"> <include name="**/*.*"/> </fileset> </copy> <copy todir="bin/lib"> <fileset dir="${hadoop.home}"> <include name="**/*.*"/> </fileset> </copy> <path id="lib-classpath"> <fileset dir="lib" includes="**/*.jar" /> </path> <pathconvert property="my.classpath" pathsep=" " > <mapper> <chainedmapper> <!-- 移除绝对路径 --> <flattenmapper /> <!-- 加上lib前缀 --> <globmapper from="*" to="lib/*" /> </chainedmapper> </mapper> <path refid="lib-classpath" /> </pathconvert> <jar basedir="bin" destfile="${jar.name}" > <include name="**/*"/> <!-- define MANIFEST.MF --> <manifest> <attribute name="Class-Path" value="${my.classpath}" /> </manifest> </jar> </target> </project>
至此,我们以及完成了,这个小项目的开发,最终回归当生产环境上,我们是需要打成jar包,在linux上定时执行的,直接使用linux环境来开发调试hadoop,遇到的问题会更少,虽然不推荐使用win直接开发hadoop程序,但是了解一些基本的方法和技巧,对我们来说也是一件不错的事情。
最后欢迎大家扫码关注微信公众号:我是攻城师(woshigcs)
本公众号的内容是有关搜索和大数据技术和互联网等方面内容的分享,也是一个温馨的技术互动交流的小家园,有什么问题随时都可以留言,欢迎大家来访!
发表评论
-
Apache Flink在阿里的使用(译)
2019-02-21 21:18 1176Flink是未来大数据实时 ... -
计算机图形处理的一些知识
2018-04-25 17:46 1229最近在搞opencv来做一些 ... -
如何在kylin中构建一个cube
2017-07-11 19:06 1269前面的文章介绍了Apache Kylin的安装及数据仓 ... -
Apache Kylin的入门安装
2017-06-27 21:27 2145Apache Kylin™是一个开源的分布式分析引擎,提供 ... -
ES-Hadoop插件介绍
2017-04-27 18:07 1992上篇文章,写了使用spark集成es框架,并向es写入数据,虽 ... -
如何在Scala中读取Hadoop集群上的gz压缩文件
2017-04-05 18:51 2131存在Hadoop集群上的文件,大部分都会经过压缩,如果是压缩 ... -
如何收集项目日志统一发送到kafka中?
2017-02-07 19:07 2792上一篇(http://qindongliang.iteye. ... -
Hue+Hive临时目录权限不够解决方案
2016-06-14 10:40 4703安装Hue后,可能会分配多个账户给一些业务部门操作hive,虽 ... -
Hadoop的8088页面失效问题
2016-03-31 11:21 4450前两天重启了测试的hadoop集群,今天访问集群的8088任 ... -
Hadoop+Hbase集群数据迁移问题
2016-03-23 21:00 2524数据迁移或备份是任何 ... -
如何监控你的Hadoop+Hbase集群?
2016-03-21 16:10 4921前言 监控hadoop的框架 ... -
Logstash与Kafka集成
2016-02-24 18:44 11630在ELKK的架构中,各个框架的角色分工如下: Elastic ... -
Kakfa集群搭建
2016-02-23 15:36 2647先来整体熟悉下Kafka的一些概念和架构 (一)什么是Ka ... -
大数据日志收集框架之Flume入门
2016-02-02 14:25 4186Flume是Cloudrea公司开源的一款优秀的日志收集框架 ... -
Apache Tez0.7编译笔记
2016-01-15 16:33 2523目前最新的Tez版本是0.8,但还不是稳定版,所以大家还 ... -
Bug死磕之hue集成的oozie+pig出现资源任务死锁问题
2016-01-14 15:52 3835这两天,打算给现有的 ... -
Hadoop2.7.1和Hbase0.98添加LZO压缩
2016-01-04 17:46 26041,执行命令安装一些依赖组件 yum install -y ... -
Hadoop2.7.1配置NameNode+ResourceManager高可用原理分析
2015-11-11 19:51 3177关于NameNode高可靠需要配置的文件有core-site ... -
设置Hadoop+Hbase集群pid文件存储位置
2015-10-20 13:40 2850有时候,我们对运行几 ... -
Hadoop+Maven项目打包异常
2015-08-11 19:36 1565先简单说下业务:有一个单独的模块,可以在远程下载Hadoop上 ...
相关推荐
【万法归宗之语法速成进阶 第6节 介词短语(1)】主要探讨了英语语法中的一个重要部分——介词短语。介词短语在英语句子中起到至关重要的作用,它们通常由介词加上名词或代词组成,能够表达地点、时间、方式、原因等...
【万法归宗之语法速成进阶 第2节 句子成分超精解的奥秘(1)】 本节课程主要聚焦于英语语法中的三大从句——名词性从句、定语从句和状语从句的学习。宋老师的教学理念强调实践与理论相结合,认为传统的教学方式往往...
* 词类是英语语法的基础之一,分为不同的类别,如名词、动词、形容词、副词等。 * 每种词类都有其特定的功能和用法,理解词类是英语语法的关键。 语法七要素二:句子成分 * 句子成分是英语语法的另一个重要组成...
万法归宗之语法速成进阶 第4节 动词时态与语态超精解(1).pdf
【万法归宗之语法速成进阶 第1讲 句子成分超精解的奥秘】课程由宋老师主讲,旨在帮助学习者快速掌握英语语法的核心概念。课程特别强调了句子成分的理解和应用,指出英语句子成分分为基本成分和修饰成分两大类。 ...
【万法归宗之语法速成进阶 第3节 三大从句从入门到精通1(1).pdf】是一份英语语法学习资料,主要聚焦于三大从句——宾语从句、状语从句和定语从句的解析与应用。课程通过引用漫威系列电影中的经典台词作为实例,帮助...
报告的核心思想是“万法归宗”,意在探讨钢铁行业中各企业的竞争策略与市场表现,以及如何在周期性行业中挖掘阿尔法(超额收益)机会。 2. 经济周期与阿尔法投资策略: 报告中提出“周期的真谛:阿尔法之路”这一...
英语语法速成进阶之句子成分超精解的奥秘 在英语语法中,句子成分是指句子中的各个组成部分,包括主语、谓语、宾语、状语、定语、同位语等。只有当我们掌握了句子成分的知识,才能更好地理解和掌握英语语法。 1. ...
4. 万华化学将继续紧贴一体化、相关多元化、精细化和低成本的发展战略,远期看聚氨酯、石化、精细化工及新材料业务将成“三足鼎立”之势,助力万华化学收入和利润增长持续性提升,公司有望崛起为综合性化工航母。
[奥莱理] WCF 服务编程 第1版 (英文版) [奥莱理] Programming WCF Services 1st Edition ============================================================ [奥莱理] WCF 服务编程 第2版 (英文版) [奥莱理] ...
自-【万股归宗指标】实战个股大揭秘-北京财经328325特供.pdf
简言之,故事线就是将项目的核心价值通过一个精彩的故事贯穿于所有营销的场景中,从而建立起客户差异化偏好的购买逻辑。 其次,故事线解决了项目在营销过程中遇到的问题。首先,它明确了项目的主要价值来龙去脉,...
从给定的文件信息中,我们可以总结出一系列与PHP编程相关的知识点,涵盖了基本概念、面试常见问题、数据库操作、安全措施、以及高级编程技巧。以下是详细的解析: ### 1. GET与POST提交方法的区别 GET和POST是HTTP...
产品经理的哲学方法论,主要探讨的是在产品设计与管理中融入哲学思维,特别是"本体自证与万物归宗"这一理念。这里的"本体自证"指的是通过深入探究事物本质来验证自身存在的合理性,而"万物归宗"则意味着在多元复杂的...
【霸王剑通达信指标公式】是用于股票交易分析的一种技术指标,主要目的是帮助投资者识别潜在的买入点。这个公式包含多个条件判断,通过综合分析价格、成交量以及移动平均线等数据来确定股票的强势程度和买入时机。...
攀登JavaScript的高峰 欢迎贡献叉车和拉车要求 :winking_face_with_tongue: :books:多读书 完成度:100% 一点一滴: 翻译的文章 你肯定不会系列 系列教程 工具集合 读书记录
《IMS资料直通车_VoLTE信令分析手册之庖丁解“萌牛”系列期刊》是一部深入探讨IMS(IP多媒体子系统)与VoLTE(Voice over LTE)信令分析的专业资料集,通过生动形象的比喻,将复杂的通信技术原理以庖丁解牛的方式...
"炒股高手语录" 本文总结了八位炒股高手的经典语录,包括Asking、钢铁战士、南中路高手、职业炒手、龙飞虎、经常站岗、陶永根、cdrr高手语录。...第四,万法归宗,方法已经无所谓了,怎么做都有道理。
251数姓名学包含了四个核心部分:(1)万数归宗灵动的251数理;(2)乾格与坤格900种配数;(3)乾格与坤格的相加和数;(4)字体五行的明、暗两种断法。这一体系能够深入揭示个人的动态表现和静态思想,通过字体五...