仓酷云

标题: JAVA网页编程之随着示例学Oozie仓酷云 [打印本页]

作者: 仓酷云    时间: 2015-1-18 11:32
标题: JAVA网页编程之随着示例学Oozie仓酷云
对于一个大型项目,如果用java来作,可能需要9个月,并且可能需要翻阅10本以上的书,但如果用ruby来作,3个月,3本书就足够了,而.net网页编程也不过3,4本书足以,这就是区别。在前一篇文章《Oozie简介》中,我们已形貌了Oozie事情流服务器,而且展现了一个十分复杂的事情流示例。我们还形貌了针对Oozie的事情流的部署和设置,和用来启动、中断和监控Oozie事情流的工具。
在本文中,我们会形貌一个加倍庞大的例子,经由过程它我们能够会商更多Oozie特征,并演示怎样来利用它们。
界说历程

我们在此形貌的事情流会完成汽车GPS探测数据的猎取历程。我们每一个小时城市以文件的情势把探测数据传送到指定的HDFS目次中[1],个中包括有这个小时以内的一切探测数据。探测数据的猎取是天天针对一天内一切的24个文件完成的。假如文件的数目是24,那末猎取历程就会启动。不然:

历程的整体完成请见
(点击能够检察年夜图)。
JAVA网页编程之随着示例学Oozie仓酷云
登录/注册后可看大图

<br>
:历程图
在此,支流程(数据猎取流程)起首会为明天和之前的六天盘算出目次的称号,然后启动(fork)七个目次的子历程(子流程)。待一切子历程的形态都酿成停止以后,join步骤就会把把持权交给end形态。
子历程启动时,起首会取得关于目次的信息——它的日期和文件数目。基于这条信息,它会决意是猎取数据仍是把数据回档,大概发送剩下的邮件,大概不做任何事情。
Directory子历程完成

以下代码卖力完成的是directory子历程(代码1)。
  1. <workflow-appxmlns=uri:oozie:workflow:0.1name=processDir><startto=getDirInfo/><!--STEPONE--><actionname=getDirInfo><!--writes2properties:dir.num-files:returns-1ifdirdoesntexist,otherwisereturns#offilesindirdir.age:returns-1ifdirdoesntexist,otherwisereturnsageofdirindays--><java><job-tracker>${jobTracker}</job-tracker><name-node>${nameNode}</name-node><main-class>com.navteq.oozie.GetDirInfo</main-class><arg>${inputDir}</arg><capture-output/></java><okto="makeIngestDecision"/><errorto="fail"/></action><!--STEPTWO--><decisionname="makeIngestDecision"><switch><!--emptyordoesntexist--><caseto="end">${wf:actionData(getDirInfo)[dir.num-files]lt0||(wf:actionData(getDirInfo)[dir.age]lt1andwf:actionData(getDirInfo)[dir.num-files]lt24)}</case><!--#offiles>=24--><caseto="ingest">${wf:actionData(getDirInfo)[dir.num-files]gt23||wf:actionData(getDirInfo)[dir.age]gt6}</case><defaultto="sendEmail"/></switch></decision><!--EMAIL--><actionname="sendEmail"><java><job-tracker>${jobTracker}</job-tracker><name-node>${nameNode}</name-node><main-class>com.navteq.oozie.StandaloneMailer</main-class><arg>probedata2@navteq.com</arg><arg>gregory.titievsky@navteq.com</arg><arg>${inputDir}</arg><arg>${wf:actionData(getDirInfo)[dir.num-files]}</arg><arg>${wf:actionData(getDirInfo)[dir.age]}</arg></java><okto="end"/><errorto="fail"/></action><!--INGESTION--><actionname="ingest"><java><job-tracker>${jobTracker}</job-tracker><name-node>${nameNode}</name-node><prepare><deletepath="${outputDir}"/></prepare><configuration><property><name>mapred.reduce.tasks</name><value>300</value></property></configuration><main-class>com.navteq.probedata.drivers.ProbeIngest</main-class><arg>-conf</arg><arg>action.xml</arg><arg>${inputDir}</arg><arg>${outputDir}</arg></java><okto="archive-data"/><errorto="ingest-fail"/></action><!—ArchiveData--><actionname="archive-data"><fs><movesource=${inputDir}target=/probe/backup/${dirName}/><deletepath=${inputDir}/></fs><okto="end"/><errorto="ingest-fail"/></action><killname="ingest-fail"><message>Ingestionfailed,errormessage[${wf:errorMessage(wf:lastErrorNode())}]</message></kill><killname="fail"><message>Javafailed,errormessage[${wf:errorMessage(wf:lastErrorNode())}]</message></kill><endname=end/></workflow-app>
复制代码
代码1:Directory子历程
这个子历程的start节点会触发自界说的java节点,这个节点会取得目次信息(代码2)。
  1. packagecom.navteq.oozie;importjava.io.File;importjava.io.FileOutputStream;importjava.io.OutputStream;importjava.util.GregorianCalendar;importjava.util.Properties;importorg.apache.hadoop.conf.Configuration;importorg.apache.hadoop.fs.FileStatus;importorg.apache.hadoop.fs.FileSystem;importorg.apache.hadoop.fs.Path;publicclassGetDirInfo{privatestaticfinalStringOOZIE_ACTION_OUTPUT_PROPERTIES="oozie.action.output.properties";publicstaticvoidmain(String[]args)throwsException{StringdirPath=args[0];StringpropKey0="dir.num-files";StringpropVal0="-1";StringpropKey1="dir.age";StringpropVal1="-1";System.out.println("Directorypath:"+dirPath+"");Configurationconf=newConfiguration();FileSystemfs=FileSystem.get(conf);PathhadoopDir=newPath(dirPath);if(fs.exists(hadoopDir)){FileStatus[]files=FileSystem.get(conf).listStatus(hadoopDir);intnumFilesInDir=files.length;propVal0=Integer.toString(numFilesInDir);longtimePassed,daysPassedLong;intdaysPassed;StringdirName=hadoopDir.getName();String[]dirNameArray=dirName.split("-");if(dirNameArray.length==3){intyear=Integer.valueOf(dirNameArray[0]);intmonth=Integer.valueOf(dirNameArray[1])-1;//monthsare0basedintdate=Integer.valueOf(dirNameArray[2]);GregorianCalendardirCreationDate=newGregorianCalendar(year,month,date);timePassed=(newGregorianCalendar()).getTimeInMillis()-dirCreationDate.getTimeInMillis();daysPassed=(int)=timePassed/1000/60/60/24;;propVal1=Integer.toString(daysPassed);}}StringoozieProp=System.getProperty(OOZIE_ACTION_OUTPUT_PROPERTIES);if(oozieProp!=null){FilepropFile=newFile(oozieProp);Propertiesprops=newProperties();props.setProperty(propKey0,propVal0);props.setProperty(propKey1,propVal1);OutputStreamos=newFileOutputStream(propFile);props.store(os,"");os.close();}elsethrownewRuntimeException(OOZIE_ACTION_OUTPUT_PROPERTIES+"Systempropertynotdefined");}}
复制代码
代码2:取得目次信息的节点
这个类会取得目次名作为输出的参数,并起首反省该目次是不是存在。假如目次不存在,那末存在工夫(age)和文件数目城市前往-1,不然,这两个值就会前往给子历程。
子历程的下一步是一个switch(决意)声明,它会决意怎样处置目次。假如目次不存在(文件数<0),大概是以后日期(存在工夫<1)而且文件数目少于24(文件数<24),那末子历程就会间接转换到停止形态。假如一切文件都位于子目次中(文件数>23)大概目次是在最少七天前创立的(存在工夫>6),那末就会有以下操纵:

对action节点的别的设置

猎取举措向你展现了别的一些Oozie设置参数,包含:

假如不是以上两种情形,那末子历程就会发送残剩的邮件,然前进出。邮件是作为另外一个java主类完成的(代码3)。
  1. packagecom.navteq.oozie;importjava.util.Properties;importjavax.mail.Message;importjavax.mail.Session;importjavax.mail.Transport;importjavax.mail.internet.InternetAddress;importjavax.mail.internet.MimeMessage;publicclassStandaloneMailer{privatestaticString_mServer="imailchi.navtech.com";privatestaticProperties_props=null;privateStandaloneMailer(){}publicstaticvoidinit(StringmServer){_mServer=mServer;_props=newProperties();_props.setProperty("mail.smtp.host",_mServer);}publicstaticvoidSendMail(Stringsubject,Stringmessage,Stringfrom,Stringto)throwsException{//createsomepropertiesandgetthedefaultSessionSessionsession=Session.getDefaultInstance(_props,null);//createamessageMessagemsg=newMimeMessage(session);//setthefromandtoaddressInternetAddressaddressFrom=newInternetAddress(from);msg.setFrom(addressFrom);String[]recipients=newString[]{to};InternetAddress[]addressTo=newInternetAddress[recipients.length];for(inti=0;i<recipients.length;i++){addressTo[i]=newInternetAddress(recipients[i]);}msg.setRecipients(Message.RecipientType.TO,addressTo);//SettingtheSubjectandContentTypemsg.setSubject(subject);msg.setContent(message,"text/plain");Transport.send(msg);}publicstaticvoidmain(String[]args)throwsException{if(args.length==5){init(_mServer);StringBuildersubject=newStringBuilder();StringBuilderbody=newStringBuilder();subject.append("Directory").append(args[2]).append("contains").append(args[3]).append("files.");body.append("Directory").append(args[2]).append("is").append(args[4]).append("daysoldandcontainsonly").append(args[3]).append("filesinsteadof24.");SendMail(subject.toString(),body.toString(),args[0],args[1]);}elsethrownewException("Invalidnumberofparametersprovidedforemail");}}
复制代码
列表3:发送提示邮件
这是利用了javax.mailAPI的复杂完成,用于发送邮件。
主历程的完成

我们已完成了子历程,然后,对主历程的完成就变得十分复杂了(列表4)[3]。
  1. <workflow-appxmlns=uri:oozie:workflow:0.1name=processDirsWF><startto=getDirs2Process/><!--STEPONE--><actionname=getDirs2Process><!--writes2properties:dir.num-files:returns-1ifdirdoesntexist,otherwisereturns#offilesindirdir.age:returns-1ifdirdoesntexist,otherwisereturnsageofdirindays--><java><job-tracker>${jobTracker}</job-tracker><name-node>${nameNode}</name-node><main-class>com.navteq.oozie.GenerateLookupDirs</main-class><capture-output/></java><okto="forkSubWorkflows"/><errorto="fail"/></action><forkname="forkSubWorkflows"><pathstart="processDir0"/><pathstart="processDir1"/><pathstart="processDir2"/><pathstart="processDir3"/><pathstart="processDir4"/><pathstart="processDir5"/><pathstart="processDir6"/><pathstart="processDir7"/></fork><actionname="processDir0"><sub-workflow><app-path>hdfs://sachicn001:8020/user/gtitievs/workflows/ingest</app-path><configuration><property><name>inputDir</name><value>hdfs://sachicn001:8020/user/data/probedev/files/${wf:actionData(getDirs2Process)[dir0]}</value></property><property><name>outputDir</name><value>hdfs://sachicn001:8020/user/gtitievs/probe-output/${wf:actionData(getDirs2Process)[dir0]}</value></property><property><name>jobTracker</name><value>${jobTracker}</value></property><property><name>nameNode</name><value>${nameNode}</value></property><property><name>activeDir</name><value>hdfs://sachicn001:8020/user/gtitievs/test-activeDir</value></property><property><name>dirName</name><value>${wf:actionData(getDirs2Process)[dir0]}</value></property></configuration></sub-workflow><okto="joining"/><errorto="fail"/></action>….<actionname="processDir7"><sub-workflow><app-path>hdfs://sachicn001:8020/user/gtitievs/workflows/ingest</app-path><configuration><property><name>inputDir</name><value>hdfs://sachicn001:8020/user/data/probedev/files/${wf:actionData(getDirs2Process)[dir7]}</value></property><property><name>outputDir</name><value>hdfs://sachicn001:8020/user/gtitievs/probe-output/${wf:actionData(getDirs2Process)[dir7]}</value></property><property><name>dirName</name><value>${wf:actionData(getDirs2Process)[dir7]}</value></property></configuration></sub-workflow><okto="joining"/><errorto="fail"/></action><joinname="joining"to="end"/><killname="fail"><message>Javafailed,errormessage[${wf:errorMessage(wf:lastErrorNode())}]</message></kill><endname=end/></workflow-app>
复制代码
代码4:数据猎取主历程
这个历程起首会触发java节点,盘算必要处置的目次列表(列表5),然后对每一个目次实行子历程,从而处置给定的目次。
  1. packagecom.navteq.oozie;importjava.io.File;importjava.io.FileOutputStream;importjava.io.OutputStream;importjava.util.Calendar;importjava.util.GregorianCalendar;importjava.util.Properties;publicclassGenerateLookupDirs{publicstaticfinallongdayMillis=1000*60*60*24;privatestaticfinalStringOOZIE_ACTION_OUTPUT_PROPERTIES="oozie.action.output.properties";publicstaticvoidmain(String[]args)throwsException{CalendarcurDate=newGregorianCalendar();intyear,month,date;StringpropKey,propVal;StringoozieProp=System.getProperty(OOZIE_ACTION_OUTPUT_PROPERTIES);if(oozieProp!=null){FilepropFile=newFile(oozieProp);Propertiesprops=newProperties();for(inti=0;i<8;++i){year=curDate.get(Calendar.YEAR);month=curDate.get(Calendar.MONTH)+1;date=curDate.get(Calendar.DATE);propKey="dir"+i;propVal=year+"-"+(month<10?"0"+month:month)+"-"+(date<10?"0"+date:date);props.setProperty(propKey,propVal);curDate.setTimeInMillis(curDate.getTimeInMillis()-dayMillis);}OutputStreamos=newFileOutputStream(propFile);props.store(os,"");os.close();}elsethrownewRuntimeException(OOZIE_ACTION_OUTPUT_PROPERTIES+"Systempropertynotdefined");}}
复制代码
代码5:目次盘算程序
结论

在这篇文章中,我们向你展现了一个更庞大的完全的事情流示例,它让我们能够演示更多的Oozie特征和对它们的使用。鄙人一篇文章中,我们会会商构建可重用的Oozie组件库,并利用自界说的节点扩大Oozie。
申谢

十分感激我们在Navteq的同事GregoryTitievsky,他为我们完成了年夜部分代码。
关于作者
BorisLublinsky是NAVTEQ公司的首席架构师,在这家公司中他的事情是为年夜型数据办理和处置、SOA和完成各类NAVTEQ的项目界说架构的愿景。他仍是InfoQ的SOA编纂,和OASIS的SOARA事情组的介入者。Boris是一名作者,还常常宣布演讲,他最新的一本书是《AppliedSOA》。
MichaelSegel在已往二十多年间一向与客户写作,辨认并办理他们的营业成绩。Michael已作为多种脚色、在多个行业中事情过。他是一名自力参谋,老是希冀可以办理一切有应战的成绩。Michael具有俄亥俄州立年夜学的软件工程学位。
参考信息

1.BorisLublinsky,MikeSegel《Oozie简介》
[1]目次的称号是汇集这条数据的日期。
[2]这是已存在的程序,对它的形貌与本文有关。
[3]在此省略了一些反复代码。
检察英文原文:OoziebyExample

java是一种面向对象的编程语言,优点是可移植性比较高,最初设计时就是本着一次编写到处执行设计的。可以开发各种应用程序和游戏,不过速度没有c++快,所以一般是不用java来编写应用程序和电脑游戏。
作者: 分手快乐    时间: 2015-1-21 09:36
学Java必读的两个开源程序就是Jive和Pet Store.。 Jive是国外一个非常著名的BBS程序,完全开放源码。论坛的设计采用了很多先进的技术,如Cache、用户认证、Filter、XML等,而且论坛完全屏蔽了对数据库的访问,可以很轻易的在不同数据库中移植。论坛还有方便的安装和管理程序,这是我们平时编程时容易忽略的一部份(中国程序员一般只注重编程的技术含量,却完全不考虑用户的感受,这就是我们与国外软件的差距所在)。
作者: 再见西城    时间: 2015-1-21 17:01
让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。
作者: 透明    时间: 2015-1-30 21:28
是一种使用者不需花费很多时间学习的语言
作者: 小魔女    时间: 2015-2-4 21:50
其实说这种话的人就如当年小日本号称“三个月拿下中国”一样大言不惭。不是Tomjava泼你冷水,你现在只是学到了Java的骨架,却还没有学到Java的精髓。接下来你得研究设计模式了。
作者: 简单生活    时间: 2015-2-10 06:49
是一种使网页(Web Page)产生生动活泼画面的语言
作者: 再现理想    时间: 2015-2-28 23:52
我大二,Java也只学了一年,觉得还是看thinking in java好,有能力的话看英文原版(中文版翻的不怎么好),还能提高英文文档阅读能力。
作者: 仓酷云    时间: 2015-3-8 14:21
接着就是EJB了,EJB就是Enterprise JavaBean, 看名字好象它是Javabean,可是它和Javabean还是有区别的。它是一个体系结构,你可以搭建更安全、更稳定的企业应用。它的大量代码已由中间件(也就是我们常听到的 Weblogic,Websphere这些J2EE服务器)完成了,所以我们要做的程序代码量很少,大部分工作都在设计和配置中间件上。
作者: 若相依    时间: 2015-3-11 18:22
Java自面世后就非常流行,发展迅速,对C++语言形成了有力冲击。Java 技术具有卓越的通用性、高效性、平台移植性和安全性,广泛应用于个人PC、数据中心、游戏控制台
作者: 因胸联盟    时间: 2015-3-16 23:21
[url]http://www.jdon.com/[/url]去下载,或到同济技术论坛的服务器[url]ftp://nro.shtdu.edu.cn[/url]去下,安装上有什么问题,可以到论坛上去提问。
作者: 蒙在股里    时间: 2015-3-17 12:18
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
作者: 兰色精灵    时间: 2015-3-24 09:59
Java是一个纯的面向对象的程序设计语言,它继承了 C++语言面向对象技术的核心。Java舍弃了C ++语言中容易引起错误的指针(以引用取代)、运算符重载(operator overloading)
作者: 只想知道    时间: 2015-3-25 05:28
让你能够真正掌握接口或抽象类的应用,从而在原来的Java语言基础上跃进一步,更重要的是,设计模式反复向你强调一个宗旨:要让你的程序尽可能的可重用。
作者: 活着的死人    时间: 2015-4-21 19:42
Java是一种计算机编程语言,拥有跨平台、面向对java
作者: 莫相离    时间: 2015-4-21 22:12
是一种将安全性(Security)列为第一优先考虑的语言
作者: 第二个灵魂    时间: 2015-4-24 02:08
当然你也可以参加一些开源项目,一方面可以提高自己,另一方面也是为中国软件事业做贡献嘛!开发者在互联网上用CVS合作开发,用QQ,MSN,E-mail讨论联系,天南海北的程序员分散在各地却同时开发同一个软件,是不是很有意思呢?
作者: 飘灵儿    时间: 2015-4-25 07:31
自从Sun推出Java以来,就力图使之无所不包,所以Java发展到现在,按应用来分主要分为三大块:J2SE,J2ME和J2EE,这也就是Sun ONE(Open Net Environment)体系。J2SE就是Java2的标准版,主要用于桌面应用软件的编程;J2ME主要应用于嵌入是系统开发,如手机和PDA的编程;J2EE是Java2的企业版,主要用于分布式的网络程序的开发,如电子商务网站和ERP系统。
作者: 变相怪杰    时间: 2015-4-26 05:10
如果要向java web方向发展也要吧看看《Java web从入门到精通》学完再到《Struts2.0入门到精通》这样你差不多就把代码给学完了。有兴趣可以看一些设计模块和框架的包等等。
作者: 乐观    时间: 2015-5-12 09:58
Pet Store.(宠物店)是SUN公司为了演示其J2EE编程规范而推出的开放源码的程序,应该很具有权威性,想学J2EE和EJB的朋友不要 错过了。
作者: 精灵巫婆    时间: 2015-7-6 08:08
你一定会高兴地说,哈哈,原来成为Java高手就这么简单啊!记得Tomjava也曾碰到过一个项目经理,号称Java很简单,只要三个月就可以学会。




欢迎光临 仓酷云 (http://ckuyun.com/) Powered by Discuz! X3.2