云计算设计模式(二十)——调度程序代理管理者模式
云计算设计模式(二十)——调度程序代理管理者模式
协调一系列在分布式服务集和其它远程资源的的行为,试图透明地处理故障,假设这些操作失败,或撤销,假设系统不能从故障中恢复执行工作的影响。这样的模式能够分布式系统中添加弹性和灵活性,使之恢复和重试失败是因为短暂的异常。持久的故障和处理故障等操作。
背景和问题
应用程序执行其包含多个步骤,当中的一些能够调用远程服务或訪问远程资源的任务。各个步骤能够是相互独立的,但它们是由实现该任务的应用程序逻辑编排。
仅仅要有可能,应用程序应该确保任务执行完毕和解决远程訪问服务或资源时可能发生的不论什么故障。可能会因各种原因,这些故障。比如,该网络可能是崩溃,通信可能被中断,远程服务可能停止响应或处于不稳定的状态,或远程资源可能临时无法訪问,可能因为资源约束。在很多情况下,这些故障可能是临时的,而且能够通过使用重试模式进行处理。
假设该应用程序检測到一个更永久的故障,从它能够不easy恢复。它必须能够将系统恢复到一致状态,并确保整个端至端的操作的完整性。
解决方式
调度代理管理者模式定义了下面角色。这些演员编排的步骤(工作。单个项目)将作为任务(整个过程)的一部分进行:
•调度安排构成的总体任务要执行,并配合它们的操作的各个步骤。可依照下列步骤组合成一个管道或工作流。而且所述调度器是负责确保在这个工作流程中的步骤,以适当的顺序被执行。作为各步骤中进行(如“步骤还未開始”。“步执行时,”或“步骤完毕”),并记录有关该状态的信息的调度器维护关于工作流的状态信息。这个状态信息也应包含的同意的步骤来完毕(称为全然按时间)的时间的上限。假设一个步骤须要訪问远程服务或资源时,调度程序调用适当的代理程序。通过它的工作的细节将被执行。调度通常採用异步请求/响应消息与代理进行通讯。这能够通过使用队列来实现,虽然也能够使用其它分布式消息传递技术来取代。
注意:
调度程序执行相似的功能,以在流程管理模式的过程管理器。实际工作流程通常被定义并通过由该调度器所控制的工作流引擎来实现。这样的方法分离了业务逻辑从调度的工作流程。
•代理包含逻辑,封装调用一个远程服务,或訪问由在一个任务的步骤中引用的远程资源。每一个代理通常通过它能够调用单个服务或资源。实施对应的错误处理和重试逻辑(如有超时限制。稍后说明)。
假设由调度程序所执行的工作流中的步骤利用在不同步骤的若干服务和资源,每一个步骤可能会引用不同代理(这是当中的模式的实现细节)。
•监监视由调度正在执行中的任务步骤的状态。
它执行周期(频率将系统专用)。检查的步骤,通过调度为保持状态。
假设检測到不论什么已超时或失败,它会安排对应的代理来恢复步骤或执行对应的补救措施(这可能涉及改动步骤的状态)。
注意,恢复或补救行动通常由调度器和代理执行。
主管应该简单地要求这些行动来执行。
调度程序,代理和管理者是逻辑组件和它们的物理实现取决于所使用的技术。
比如,若干个逻辑代理能够被实现为一个单一的网络服务的一部分。
调度器维护关于任务的进度和持久的数据存储中的每一个步骤中。被称为状态存储的状态信息。
主管能够使用此信息来帮助确定一个步骤是否出现问题。图1说明了调度程序的代理,监事和状态存储之间的关系。
图1 - 在调度程序代理管理者模式的演员
注意:
此图显示的模式的简化图。在实际的实现中。有可能是调度程序的多个实例同一时候执行的任务的每一个子集。相似地,系统能够执行每一个代理程序的多个实例,或者甚至多个监控器。
在这样的情况下,主管必须协调其与对方认真的工作。以确保它们不会争来恢复相同失败的步骤和任务。在领导人选举模式提供一个可能的攻克了这个问题。
何时一个应用程序希望执行一个任务。它提交一个请求给调度程序。
调度记录有关的任务及其步骤(比如,“步骤还未開始”)中的状态存储的初始状态的信息。然后開始执行由流程定义的操作。作为调度程序開始每一步时,它将更新关于该步骤中的状态存储(比如。“步执行的”)的状态的信息。
假设一个步骤引用远程服务或资源时,调度程序将消息发送给适当代理。该消息能够包含代理须要传递给服务或訪问该资源,除了完整的通过时间的操作的信息。假设代理成功完毕其操作时,它返回到调度程序的响应。
然后调度程序能够更新在状态存储的状态信息(比如。“步骤完毕”),并进行下一步骤。这个过程继续,直到整个任务完毕。
代理能够实现随意重试逻辑须要执行它的工作。可是,假设该代理之前。完毕未完毕其工作期间届满的调度程序就会觉得操作失败。在这样的情况下,代理应该停止其工作,并没有试图东西返回到调度程序(甚至没有错误消息),或者进行不论什么形式的恢复。
这样做的原因的限制是。后一步骤中已超时或失败,则代理的还有一个实例可被调度来执行失败的步骤(该过程将在后面描写叙述)。
假设代理本身出现问题时,调度程序将不会收到回复。该模式可能不会让这一步骤已超时,一个已经失败的真正差别。
假设一个步骤超时或失败时。状态存储将包含一个记录。指出该步骤是否正在执行(“步骤执行”),但全然通过时间已经过去了。监事查找步骤,如本,并试图恢复它们。
一个可能的策略是为超级更新完毕由值来扩展可用来完毕步骤的时间。然后将消息发送到调度器识别已超时的步骤。然后。调度程序能够尝试反复此步骤。然而,这样的设计要求为幂等的任务。
这可能是必需的管理者防止假设连续失败或者超时被重试相同步骤。为了实现这一点。对管理可维持一个重试计数为每一步,随着状态信息,在该状态存储。
假设该计数超过预定阈值的管理者能够採用一种策略。比如,通知它应重试步骤中,在期望的故障将在这段时间内能够解决调度之前等待较长的时间。或者。该管理者能够将消息发送到调度请求将整个任务通过实现补偿交易被撤消(该方法将依赖于调度程序和代理提供所必需的信息,以实现对已成功完毕各步骤的补偿操作)。
注意:
这不是管理者的目的来监控调度程序和代理商,假设他们不能又一次启动它们。
系统的这方面应该由当中这些组件所执行的基础设施进行处理。相同。管理者不应该是由调度所执行的任务正在执行(包含怎样补偿应这些任务失败)的实际业务运作的知识。这是由调度程序执行的工作流逻辑的目的。监事的责任是确定的步骤是否已失败,并安排要么为它反复或者包含失败的步骤,整个任务被取消。
假设该调度程序是失败的。或者工作流程后,又一次启动正在由调度程序进行意外终止,该调度程序应能确定不论什么飞行任务。这是处理失败时的状态,并准备继续这个任务从该点上失败了。
该方法的实现细节都可能是特定的系统。假设任务不能恢复。这可能是必要的。以撤消该任务已经完毕的工作。这可能还须要执行一个补偿事务。
这样的模式的主要长处是。该系统是弹性的意想不到的临时或不可恢复故障的情况下。
该系统能够构造成可自愈。比如,假设一个代理程序或调度程序崩溃时,一个新的可启动的,因而管理能够安排要恢复的任务。假设管理者发生问题,还有一实例能够启动。而且能够从发生问题的接管。
假设管理者计划定期执行,一个新的实例能够被自己主动提前定义的时间间隔后启动。该状态存储能够被复制以实现更大程度的弹性。
问题和注意事项
在决定怎样实现这个模式时,您应考虑下面几点:
•该图案能够是平庸的执行,而且须要的系统的每一个可能的故障模式的全面測试。
•通过调度实现的恢复/重试逻辑能够是复杂的而且依赖于状态存储保持状态信息。
它也可能是必要的,记录在一个持久的数据存储区执行一个补偿事务处理所需的信息。
•与监事执行是很重要的频率。它应该执行足够频繁。以防止不论什么失败阻塞长时间的应用程序的步骤,但它不应该执行很频繁,它成为一个开销。
•由代理执行的步骤能够被执行一次以上。实现这些步骤的逻辑应该是幂等。
何时使用这个模式
使用这样的模式时。在分布式环境中执行,比如云的方法必须是有弹性的,以通信故障和/或执行故障。
这样的模式可能不适合任务不调用远程服务或訪问远程资源。
样例
实现一个电子商务系统中的Web应用程序已经部署在微软的Azure。用户能够执行此应用程序来浏览提供一个组织的产品,下订单,这些产品。用户接口执行作为一个网络的作用。而且该应用程序的命令处理元件被实现为一组工作角色。
订单处理逻辑的一部分包含訪问远程服务,该系统的这一方面可能是易发生的瞬态或更持久的故障。
为此。设计师使用了调度程序代理管理者模式实现了系统的订单处理单元。
当客户下订单时,应用程序构建了一个消息,说明的顺序和该职位的消息到队列中。一个单独的提交过程中。工人的角色执行,检索此消息。将订单到订单数据库的具体信息,并为在国家商店的订单流程的记录。请注意,插入到常规数据库和国家存储作为同一操作的一部分执行。提交过程的设计,以确保两个刀片共同完毕。
该提交进程创建的订单包含状态信息:
•订单ID:在订单数据库中的订单的ID。
•LockedBy:的辅助角色的处理顺序的实例ID。
有可能是执行调度程序的工人角色的多个电流情况下,但每一个订单仅仅能通过一个实例来处理。
•CompleteBy:通过该命令应处理的时间。
•ProcessState:任务处理订单的当前状态。可能的状态是:◦Pending。的顺序已被创建,但处理尚未启动。
◦Processing。
该命令正在处理中。
◦Processed。订单已成功处理。
◦Error。订单处理失败。
•FailureCount:次数的处理已经尝试了顺序的号码。
在这样的状态信息,OrderID字段从新订单的订单ID复制。该LockedBy和CompleteBy字段设置为null,则ProcessState字段设置为待定,而且FailureCount字段设置为0。
注意:
在这个样例中,为了处理逻辑比較简单,仅仅包含一个调用的远程服务的单个步骤。在一个更复杂的多步骤的情况下。提交过程很可能涉及多个步骤,所以多个记录将在状态存储,每一个描写叙述了一个单独的步骤中的状态被创建。
该调度程序同一时候作为一个辅助角色的一部分。实现了处理订单的业务逻辑。调度轮询新订单的一个实例探讨了状态存储的记录。当中LockedBy字段为空。并在ProcessState场待定。何时调度程序发现一个新的订单,立马填充LockedBy字段与它自己的实例ID,设置CompleteBy字段到一个适当的时间。并设置ProcessState字段来处理。
执行此代码的设计是独特和原子,以确保调度程序的两个并发实例不能试图同一时候处理的顺序相同。
调度程序将执行业务流程处理订单异步,从状态存储传递给它的值在OrderID字段。
工作流处理的顺序检索来自数据库的订单订单的具体信息。并执行其工作。当订单处理流程的步骤须要调用远程服务,它使用一个代理。在工作流步骤的代理通过利用对作为请求/响应信道Azure的服务总线消息队列进行通信。
图2示出了该解决方式的一个高层视图。
图2 - 使用调度程序代理管理者模式在Azure的解决方式来处理订单
从一个工作流步骤发送到代理的消息描写叙述的顺序。并包含CompleteBy时间。假设代理接收来自远程服务的响应的CompleteBy时间到期之前,构建其上的服务总线队列在其上的工作流是听张贴答复消息。当工作流步骤接收到有效的应答消息。它完毕它的处理和调度台的订单状态ProcessState场处理。在这一点上,为了处理已成功完毕。
假设CompleteBy时间到期的代理接收来自远程服务的响应之前。代理简单地停止其处理。并终止处理顺序。相似地,假设工作流处理的顺序超过了CompleteBy时,它也将终止。在这两种情况下。在该状态存储在顺序的状态保持给定处理中,但CompleteBy时间指示的时间用于处理订单已经过去,该处理判定为不合格。请注意。假设正在訪问远程服务。或者正在处理的顺序工作流(或两者)的代理意外终止。在状态存储的信息将再次保持设置为处理,终于将有过期CompleteBy值。
假设代理检測到不可恢复的非瞬时性故障当它正在尝试联系远程服务。它能够发送一个错误响应返回到工作流。该调度程序能够设置为错误,并提出了警示操作者的事件的状态。然后,操作者能够尝试手动解决失败的原因。并又一次提交失败的处理步骤。
主管定期检查状态存储在寻找订单,过期CompleteBy值。假设管理者发现这样的记录,它添加了FailureCount领域。
假设FailureCount值低于规定的阈值时。所述管理者复位LockedBy字段为空,更新CompleteBy场与新的到期时间,并设置ProcessState字段待定。调度程序的一个实例能够拿起这个命令并执行其处理如前。假设FailureCount值超过特定阈值时,对故障的原因被假定为非瞬态。
监事设置为错误的状态。并引发了警报操作,如前所述的事件。
注意:
在这个样例中。管理者是在一个单独的工作任务落实。
您能够使用各种策略来安排监理任务执行,包含使用Azure的计划程序服务(不要与计划程序组件在此模式相混淆)。关于Azure的计划程序服务的很多其它信息,请訪问调度程序页面。
虽然未在本实施例中所看到的,该调度程序可能须要保留在通知关于单的进度及状态首位提交的顺序应用。应用程序和调度程序彼此分离。以消除它们之间的不论什么相关性。该应用程序并不知道哪个调度的实例处理的顺序,调度不知道它的具体应用实例公布的顺序。
为使订单状态予以报道,该应用程序能够使用自己的私人响应队列。这个响应队列的具体信息将被纳入送往提交过程的要求,当中包含在状态存储这些信息的一部分。
该调度程序随后将邮件投递到该队列表示订单的状态(“接收到的请求”。“为了完毕”,“订单失败”。等等)。它应包含订单ID在这些消息中。以便它们能够与由该应用程序的原始请求相关联。
本文翻译自MSDN:http://msdn.microsoft.com/en-us/library/dn589780.aspx