数据中心由多种资源组成,包括物理(如存储、服务器)和虚拟(如虚拟机)。IaaS软件本质上是管理各种资源的状态;例如,创建虚拟机通常会改变存储的状态(在商店上创建新的磁盘)、网络的状态(在网络上设置DHCP/DNS/NAT等)和虚拟状态。机器管理程序(在虚拟机管理程序上创建)一个新的虚拟机。与普通应用程序不同,大多数应用程序管理存储在内存或数据库中的状态。为了反映数据中心的整体状态,IAAS软件必须管理分散在每个设备中的状态,从而导致长的执行路径。IaaS软件任务通常涉及多个设备上的状态改变,在任何步骤都可能发生错误,然后系统处于中间状态,也就是说,一些设备已经改变了状态,有些则没有。例如,当创建虚拟机时,用于配置IaaS软件的VM网络的常规步骤是DHCP DNS SNAT。如果在创建SNAT时发生错误,则先前配置的DHCP和DNS很可能保留在系统中,因为即使在最后没有成功创建虚拟机,它们也已经成功应用。这种不一致的状态通常会导致云层不稳定。
另一方面,在传统的IaaS软件中,硬编码的业务逻辑是不灵活的,为了改变,开发人员经常不得不重写或修改现有代码来改变某些已建立的行为,从而影响软件的稳定性。
解决这些问题的方法是引入工作流的概念,将整个业务逻辑分解成细粒度的回滚步骤,以便软件能够清理生成的错误的状态并使软件可配置。
注意:在ZStad中,我们可以调用工作流“流程”中的步骤,在下面的文章中,流程(流程)和步骤(步骤)是可互换的。
问题
错误处理一直是软件设计中的头疼问题。即使现在每个软件工程师都知道错误处理的重要性,但事实上,他们仍然在找借口来忽略它。巧妙的错误处理是困难的,特别是在任务可以跨多个组件的系统中。即使有经验的工程师能够注意自己代码中的错误,他们也不能为他们不写的组件做出类似的努力,如果整个体系结构不是强制性的,那么它可以以全局的方式增强错误处理的机制。忽略错误处理在IaaS软件中尤其有害。不同于通过重新启动恢复所有状态的消费程序,IaaS软件通常不能恢复其自身状态,并且将要求管理员手动在数据库和外部设备中出错。一个不一致的状态可能不会导致任何大的问题,甚至可能不会被注意到,但是这种不一致状态的持续积累最终会在某个时刻破坏整个云系统。
在这里相信有许多想要学习大数据的同学,大家可以加下大数据学习群532218147,即可免费领取一整套系统的大数据学习教程
工作流引擎
工作流是一种将一些繁琐的方法调用分解成细粒度的步骤,它集中在一件事情上。它由一个序列或状态机驱动来完成一个完整的任务。在配置回滚处理程序之后,工作流在某个步骤发生错误或未处理异常时,可以中止执行并回滚所有先前的执行步骤。以创建虚拟机为例,主工作流看起来像:
序列工作流是由链式设计模式(链式模式)生成的,具有可预测的执行序列,是ZStad工作流的基础。一个流本质上是一个可以包含子过程和后才可以完成以前所有的流程执行java接口。
公共接口流{
空隙运行(FlowTrigger trigger,地图数据);
空隙回滚(FlowTrigger trigger,地图数据);
}
在流程界面中,当工作流前进到这个过程(流程)时,将调用Run(FlowTrigger trigger,MAP数据)方法;参数映射数据可以用来从先前的进程(流)获得数据,并将数据传递给后续的进程(流)。当它完成时,进程(流程)调用ToGr.NeXT(引导)工作流(工作流)来执行下一个进程(流程);如果发生错误,进程(流)应该调用TrutGel.Valt(ErrOrror Error)方法来中止执行,并通知工作流(工作流)回滚完成。D流。进程(包括失败的进程本身)调用它们各自的回滚()方法。
在FlowChain接口中建立的过程代表一个完整的工作流。创建FlowChain有两种方法:
1。陈述式
该过程可以在组件的Spring配置文件中配置,并且可以通过向FlowChainBuilder填充进程的类名称的列表来创建流程链。
这是创建包含可重用进程的严重可配置工作流的典型方法。在上面的示例中,该工作流的目的是创建用户VM;所谓的应用VM具有与分布式虚拟机网卡外部基本相同的相同进程,因此设备VM和用户VM进程配置A的单个进程配置。最共享:
注意:在上一张图片中,我们强调了Apple ServestMultLogATeNICFLUE流程为Green,这是创建用户VM和VM应用的工作流步骤的唯一不同地方。
2。程序设计方法
流程链也可以以编程方式创建。当创建工作流是微不足道的,并且该过程是不可重用的时,通常使用此方法。
FuffChin链= FuffChin Buffeld. NeimSimple流链();
链表名称(“测试”);
SeDATA(NeWHASMAP);
Chain.then(NeWFLASH){()
StrugIn NaMeEng= =“FLUT1”;
@重写
Publicvoidrun(FlowTriggertrigger,MaDATA){
*做一些生意*/
Trigger.next();
}
@重写
公共VoIP回滚(FlowTriggertrigger,MaDATA){
/*回滚某物*
Trigger.rollback();
}
“}”然后(NeWFLASH(){)
StrugIn NaMeEng= =“Fuff2”;
@重写
Publicvoidrun(FlowTriggertrigger,MaDATA){
*做一些生意*/
Trigger.next();
}
@重写
公共VoIP回滚(FlowTriggertrigger,MaDATA){
/*回滚某物*
Trigger.rollback();
}
“完成”(NeXFraveNeDebug(){)
@重写
Publicvoidhandle(MaDATA){
*工作流已成功完成*
}
“}”.Nebug(NeXFraveRoWorkter)({)
@重写
Publicvoidhandle(ErrorCodeerrCode,MaDATA){
*工作流失败,错误*//
}
}启动();
上述形式不方便使用,因为在流中,可以使用地图数据来交换数据,并且每个进程必须冗余地调用DATA GET()和DATA PUT()函数。在类似DSL的方式中,流可以通过变量共享数据:
FuffChin链= FuffChin Buffeld.NexSealFuffon链();
链表名称(“测试”);
Chain.then(NexSyfSt流()){()
StReDATA1=“数据可以被定义为类变量”;
{
DATA1=“数据可以在对象初始化器中进行初始化”;
}
@重写
Publicvoidsetup(){
FialStReDATA2= =“数据也可以在方法范围内定义,但它却”;
流(NeXFLUE){()
StrugIn NaMeEng= =“FLUT1”;
@重写
Publicvoidrun(FlowTriggertrigger,MaDATA){
DATA1=“我们可以在这里改变数据”;
STRIGUSEDATA2=DATA2;
*做某事*
Trigger.next();
}
@重写
公共VoIP回滚(FlowTriggertrigger,MaDATA){
*做一些回滚*
Trigger.rollback();
}
(});
流(NealNoRealFraceFuffy)({)
StrugIn NaMeEng= =“Fuff2”;
@重写
Publicvoidrun(FlowTriggertrigger,MaDATA){
** DATA1是我们在流1**中改变的值。
STRIGUSEDATA1=DATA1;
*做某事*
Trigger.next();
}
(});
完成(NeXFruteNoDeLever)({)
@重写
Publicvoidhandle(MaDATA){
*工作流已成功完成*
}
(});
错误(NeXFraveRoWorkter)({)
@重写
Publicvoidhandle(ErrorCodeerrCode,MaDATA){
*工作流失败,错误*//
}
(});
}
}启动();
另外,大数据初学者有什么不懂的可以关注微信公众号程序员大牛和转发——我刚整理了一份大数据2018最新的0基础入门和进阶教程,无私分享