|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有帐号?立即注册
x
一般的指的.net就是跟net网页编程相对的那种,主要是做企业级应用的。你如果想学这个,主要就是学C#和数据库。(ASP.NET好像很重要的,应该也要学的,ASP.NET上好像可以结合VB和C#等多种语言,但是微软主推C#)在后面的两篇文章中[1,2],我们形貌了Oozie事情流服务器,而且展现了几个事情流的示例。我们还形貌了针对Oozie的事情流的部署和设置,和用来启动、中断和监控Oozie事情流的工具。
在本文中,我们会向你展现Oozie的可扩大性,并申明它是怎样撑持我们完成自界说的、协同事情的言语扩大。
为何必要自界说节点(CustomNode)?
正如我们在文章[1]中所申明的,Oozie之以是不同凡响,是由于它供应了一种“最小化”的事情流言语,个中只包括多数几种把持和举措节点。只管个中的一种举措节点是java举措节点,它让我们能够从Oozie事情流挪用恣意一个带有main办法的java类,但这类办法并不是老是最好的。缘故原由之一就在于,java举措是在Hadoop丛聚中作为map-reduce功课实行的,而且只带有独一的Mapper义务。一方面,这带来了良多优点:
- 它具有内建的可伸缩性和对map/reduce框架的劫难恢复撑持,如许我们就不用这些特征构建到Oozie中。
- 内部实行机制,这让Oozie引擎变得更轻量级,从而能够撑持更多并发运转的历程。
另外一方面,这类办法也有一些弱点:
- 它把每一个java节点都作为mapper义务启动,这会招致在Hadoop丛聚中启动新的JVM而发生分外的开支。
- 在内部实行java类招致了分外的收集传输,用于与Oozie服务器同步这些实行了局。
- 从java节点传送参数成了十分泯灭资本的操纵。
只管云云,在运转工夫绝对较长(几分钟乃至几小时)的map/reduce大概Pig功课中,优点会年夜年夜凌驾负载的弱点,可是,在复杂的java节点中(拜见[2]),我们就必要注重内部实行所招致的开支了。以是,利用自界说举措节点的缘故原由之一,就是为了撑持在Oozie的实行高低文中间接实行轻量级的java类[1]。
利用自界说举措的另外一个缘故原由是为了进步事情流的语义和可读性。因为Oozie是一种撑持基于Hadoop处置组件的事情流引擎,以是它的语法完整是以Hadoop实行为中央的——Hadoop文件体系、map/reduce、Pig等等。这类语法可以很好地切合Hadoop开辟者的习气,可是并没有触及到太多关于给定举措的功效信息。我们能够为举措自己制订与营业相干的定名转换划定规矩,但这只是出格用来办理成绩的——对举措的定名只反应了给定历程的语法,既不是整体上的主题范畴,也不克不及办理举措参数的成绩,那些成绩仍旧只能由开辟者来办理。
侥幸的是,Oozie撑持十分棒的扩大机制——自界说举措节点[3],它让我们能够很简单地办理这两个成绩。自界说的举措节点让我们可使用附加的举措(动词)来扩大Oozie的言语。Oozie的举措节点能够是同步的,也能够是异步的。
- 同步节点——它在Oozie外部实行,在持续实行之前会守候这些节点完成举措。这些节点是为轻量级的义务所用的,像自界说盘算,文件体系的挪动、创立目次、删除等等。
- 异步节点——它是由Oozie启动的,可是在Oozie引擎的内部实行,它会监控正在实行的举措,直到完成。这是经由过程举措的回调大概Oozie针对举措形态的polling操纵完成的。
完成Oozie自界说举措处置程序
在这个例子中,我们会对自力的邮件程序举行转换,并展示到自界说的email举措中[2](代码1)。- packagecom.navteq.assetmgmt.oozie.custom;importjava.util.Properties;importjava.util.StringTokenizer;importjavax.mail.Message;importjavax.mail.Session;importjavax.mail.Transport;importjavax.mail.internet.InternetAddress;importjavax.mail.internet.MimeMessage;importorg.apache.oozie.ErrorCode;importorg.apache.oozie.action.ActionExecutor;importorg.apache.oozie.action.ActionExecutorException;importorg.apache.oozie.action.ActionExecutorException.ErrorType;importorg.apache.oozie.client.WorkflowAction;importorg.apache.oozie.util.XmlUtils;importorg.jdom.Element;importorg.jdom.Namespace;publicclassEmailActionExecutorextendsActionExecutor{privatestaticfinalStringNODENAME="eMail";privatestaticfinalStringSUCCEEDED="OK";privatestaticfinalStringFAILED="FAIL";privatestaticfinalStringKILLED="KILLED";privatestaticfinalStringDEFAULMAILSERVER="imailchi.navtech.com";privatestaticfinalStringEMAILSERVER="emailServer";privatestaticfinalStringSUBJECT="emailSubject";privatestaticfinalStringMESSAGE="emailBody";privatestaticfinalStringFROM="emailFrom";privatestaticfinalStringTO="emailTo";publicEmailActionExecutor(){super(NODENAME);}@Overridepublicvoidcheck(Contextcontext,WorkflowActionaction)throwsActionExecutorException{//ShouldnotbecalledforsynchoperationthrownewUnsupportedOperationException();}@Overridepublicvoidend(Contextcontext,WorkflowActionaction)throwsActionExecutorException{StringexternalStatus=action.getExternalStatus();WorkflowAction.Statusstatus=externalStatus.equals(SUCCEEDED)?WorkflowAction.Status.OK:WorkflowAction.Status.ERROR;context.setEndData(status,getActionSignal(status));}@OverridepublicbooleanisCompleted(Stringarg0){returntrue;}@Overridepublicvoidkill(Contextcontext,WorkflowActionaction)throwsActionExecutorException{context.setExternalStatus(KILLED);context.setExecutionData(KILLED,null);}@Overridepublicvoidstart(Contextcontext,WorkflowActionaction)throwsActionExecutorException{//GetparametersfromNodeconfigurationtry{ElementactionXml=XmlUtils.parseXml(action.getConf());Namespacens=Namespace.getNamespace("uri:custom:email-action:0.1");Stringserver=actionXml.getChildTextTrim(EMAILSERVER,ns);Stringsubject=actionXml.getChildTextTrim(SUBJECT,ns);Stringmessage=actionXml.getChildTextTrim(MESSAGE,ns);Stringfrom=actionXml.getChildTextTrim(FROM,ns);Stringto=actionXml.getChildTextTrim(TO,ns);//Checkifallparametersarethereif(server==null)server=DEFAULMAILSERVER;if((message==null)||(from==null)||(to==null))thrownewActionExecutorException(ErrorType.FAILED,ErrorCode.E0000.toString(),"Notallparametersaredefined");//ExecuteactionsynchronouslySendMail(server,subject,message,from,to);context.setExecutionData(SUCCEEDED,null);}catch(Exceptione){context.setExecutionData(FAILED,null);thrownewActionExecutorException(ErrorType.FAILED,ErrorCode.E0000.toString(),e.getMessage());}}//SendinganemailpublicvoidSendMail(Stringserver,Stringsubject,Stringmessage,Stringfrom,Stringto)throwsException{//createsomepropertiesandgetthedefaultSessionPropertiesprops=newProperties();props.setProperty("mail.smtp.host",server);Sessionsession=Session.getDefaultInstance(props,null);//createamessageMessagemsg=newMimeMessage(session);//setthefromandtoaddressInternetAddressaddressFrom=newInternetAddress(from);msg.setFrom(addressFrom);//ToisacommaseparatedlistStringTokenizerst=newStringTokenizer(to,",");String[]recipients=newString[st.countTokens()];intrc=0;while(st.hasMoreTokens())recipients[rc++]=st.nextToken();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);}}
复制代码 代码1:Email自界说举措
这个完成对ActionExecutor[2]类(由Oozie供应)举行了扩大,偏重写了一些需要的办法。由于邮件的发送历程是一种十分疾速的操纵,以是我们决意将实在现为同步的举措处置程序,那意味着它会在Oozie的实行高低文中实行。
我们的完成(代码1)遵守了Oozie文档并完成了一切必须的办法:
- 关于一切自界说举措处置程序都必要没有参数的机关函数。这个机关函数会注册举措处置程序的称号(利用举措称号来挪用父类),我们会在事情流XML中利用它。
- 我们可使用InitActionType[3]办法来注册实行举措时大概产生的非常,和它们的范例和毛病信息,并为实行程序自己实行初始化操纵。
- Start办法是用来启动举措的实行操纵的。由于我们完成的是同步举措,以是全部举措城市在此实行。这个办法是由Oozie挪用的,它有两个参数:Context和WorkflowAction。Context参数供应了对Oozie事情流实行高低文的会见,个中次要包括了事情流的变量,并供应了对其举行操纵的十分复杂的API(set、get)[4]。而WorkflowAction则供应了Oozie对以后举措的界说。
- 另有Check办法,Oozie会利用它来反省举措的形态。它不克不及作为同步举措来挪用。
- Kill办法,能够用来中止运转的功课大概举措。
- End办法,能够用于一切清算举措,大概用于大概在完成举措以后所要做的处置。它还必要设置实行的了局。
部署并利用Oozie自界说举措处置程序
完成了自界说的举措实行体例以后,我们必要为新的email举措界说XML形式[5](代码2)。- <?xmlversion="1.0"encoding="UTF-8"?><xs:schemaxmlns:xs="http://www.w3.org/2001/XMLSchema"xmlns:email="uri:custom:email-action:0.1"elementFormDefault="qualified"targetNamespace="uri:custom:email-action:0.1"><xs:complexTypename="EMAIL"><xs:sequence><xs:elementname="emailServer"type="xs:string"minOccurs="0"maxOccurs="1"/><xs:elementname="emailSubject"type="xs:string"/><xs:elementname="emailFrom"type="xs:string"/><xs:elementname="emailTo"type="xs:string"/><xs:elementname="emailBody"type="xs:string"/></xs:sequence></xs:complexType><xs:elementname="eMail"type="email:EMAIL"></xs:element></xs:schema>
复制代码 代码2:为email组件所用的XMLschema
自界说举措节点和XMLschema文件都必要打包在独自的jar文件中,例如说emailAction.Jar。我们可使用Oozie的oozie-setup.sh剧本实行上面的命令,从而把这个(和其他一切)jar文件增加到Oozie的war文件中。- $bin/oozie-setup.sh-jarsemailAction.jar:mail.jar(SeeAddingJarstoOozie)
复制代码 代码3:部署命令
向Oozie增加Jar文件
你要晓得,Cloudera保举的oozie-setup.sh命令行会从头构建你的war文件,而且,假如你利用网页来监控功课,那末就会丧失java的剧本扩大。在测试方面,我们难以同时包括-extjs和-jars选项。作为权宜之计,我们会把jar文件复制到${CATALINA_BASE}/webapps/oozie/WEB-INF/lib中,个中${CATALINA_BASE}代表的是/var/lib/oozie/oozie-server。请注重,这里存在必定的风险,假如其别人从头构建了war文件,那末你就会丧失这些扩大,而且他们今后必要手动增加。关于测试来讲,我们倡议复制jar文件,但是,关于临盆情况,我们倡议把jar增加到war文件中。
如今我们必要把关于自界说实行器的信息注册到Oozie的运转时中。这是经由过程扩大oozie-site.xml完成的[6]。我们能够经由过程在Oozie设置文件oozie-site.xml中增加大概修正“oozie.service.ActionService.executor.ext.classes”[7]来注册自界说举措自己(代码4)。- ……………………………………<property><name>oozie.service.ActionService.executor.ext.classes</name><value>com.navteq.assetmgmt.oozie.custom.EmailActionExecutor</value></property>……………………………………
复制代码 代码4:自界说实行设置
为新举措(代码2)所用的XMLschema应当增加到oozie-site.xml中,位于属性“oozie.service.WorkflowSchemaService.ext.schemas”[8]之下(代码5)。- ………………………………………<property><name>oozie.service.SchemaService.wf.ext.schemas</name><value>emailAction.xsd</value></property>…………………………………
复制代码 代码5:自界说形式设置
最初,Tomcat启动以后,我们就能够在事情流中利用自界说的举措节点了。
为了测试我们的完成,我们创立了复杂的事情流(代码6),它会利用我们的实行器来发送email。- <!--Copyright(c)2011NAVTEQ!Inc.Allrightsreserved.TestemailOozieScript--><workflow-appxmlns=uri:oozie:workflow:0.1name=emailTester><startto=simpleEmail/><actionname=simpleEmail><eMailxlmns=“uri:custom:email-action:0.1”><emailSubject>test</emailSubject><emailFrom>mike.segel@<mycompany>.com</emailFrom><emailTo>boris.lublinsky@<mycompany>.com</emailTo><emailMessage>Thisisatestmessage,ifyoucanseethis,Mikeydidsomethingright!:)</emailMessage></eMail><errorto="fail"/><okto="end"/></action><killname="fail"><message>Workflowfailed,errormessage[${wf:errorMessage(wf:lastErrorNode())}]</message></kill><endname=end/></workflow-app>
复制代码 代码6:利用email自界说举措实行器的复杂事情流
结论
在这篇文章中,我们展现了怎样经由过程创立自界说的举措实行器来扩大Oozie。如许做让我们能够界说和完成部门大概企业公用的Oozie言语(范畴公用言语),个中具有部门大概企业的功效。如许的范畴公用言语可以简化特定部门大概企业的构建历程,并进步代码的可读性。
只管Oozie绝对还不敷成熟,可是它已为处置包括多个map/reduce功课、而且可以向整体的营业历程增加非map-reduce功课的历程供应了基础的框架。跟着愈来愈多的用户利用Oozie并供应反应,我们信任它有充足的潜力,能够成为Hadoop情况中壮大的集成部分。
关于Oozie来讲,另有良多我们没有在这三篇文章中包括的内容。我们只是希冀它们能够引发你对Oozie事情流引擎的充足乐趣,而且可以成为进一步研讨Oozie的不错的出发点。
参考信息
- BorisLublinsky,MikeSegel.IntroductiontoOozie.
- BorisLublinsky,MikeSegel.OoziebyExample
- OoziecustomActionNodes
- Ooziesourcecode
关于作者
BorisLublinsky是NAVTEQ公司的首席架构师,在这家公司中他的事情是为年夜型数据办理和处置、SOA和完成各类NAVTEQ的项目界说架构的愿景。他仍是InfoQ的SOA编纂,和OASIS的SOARA事情组的介入者。Boris是一名作者,还常常宣布演讲,他最新的一本书是《AppliedSOA》。
MichaelSegel在已往二十多年间一向与客户写作,辨认并办理他们的营业成绩。Michael已作为多种脚色、在多个行业中事情过。他是一名自力参谋,老是希冀可以办理一切有应战的成绩。Michael具有俄亥俄州立年夜学的软件工程学位。
[1]这类类的例子多是各类计数器操纵、复杂的盘算等等。
[2]一切Oozie举措实行器都是Oozie分发程序的一部分,它们都是经由过程扩大这个类完成的。
[3]在我们的完成中,我们利用的是默许的完成,如许就是为何没有在代码中展示的缘故原由。你能够检察一下Oozie的源代码[4],就能够晓得在现存的Oozie举措处置程序中是怎样完成这个办法的。
[4]设置自界说实行器有两种体例——事情流变量和/或举措设置。在我们的例子中展现的是后者,可是在实践情形中,实践上老是两者的组合。
[5]确保不但要界说庞大的范例,还要对元素举行界说。那是Oozie所希冀的。
[6]一般在Oozie的分发包中叫做oozie-default.xml。
[7]关于多个实行器,类名应当以逗号分开。
[8]关于屡次实行,我们能够为多种形式利用逗号分开的列表。
检察英文原文:ExtendingOozie
实不相瞒,net网页编程是我见过的执行效率最低的程序设计语言,前不久在CSDN论坛上有个评测,计算9999的阶乘,同样的循环算法,net网页编程的耗时是.NET的5倍。 |
|