Orleans 2.0 官方文档 —— 6.2 部署 -> 处理故障

处理故障

注意:本文档中的所有以下指南均作为示例和思考。您不应该将它们视为解决问题的规范性解决方案,因为故障处理是一个特定于应用程序的主题。这些模式和其他模式,只有在充分了解正在使用的具体案例的情况下才有用。

在分布式系统编程中,最困难的事情是处理故障。Actor模型及其工作方式,使得处理不同类型的故障变得更加容易,但作为开发人员,您要负责考虑可能的故障,并以适当的方式处理它们。

故障的类型

当您对grain进行编写代码时,所有的调用都是异步的,并且有可能跨越网络。每次grain调用,都有可能由于以下原因之一而失败。

  • 由于网络分区崩溃或其他原因,grain在目前不可用的silo上被激活。如果silo尚未宣布死亡,您的请求可能会超时。
  • grain方法调用可能抛出异常,表明它失败了,并且无法继续其作业。
  • grain的激活体不存在且无法创建,因为OnActivateAsync方法抛出异常或死锁。
  • 网络故障不允许您在超时之前与grain通信。
  • 其他潜在的原因

故障的检测

获取对grain的引用总是成功的,并且是本地操作。但是,方法调用可能会失败,一旦失败,就会出现异常。您可以按需要的任意级别捕获异常,甚至可以跨silo传播它们。

从失败中恢复

在Orleans,恢复工作的一部分是自动的,如果grain不再可访问,Orleans将在下一个方法调用中重新激活它。在应用程序的上下文中,状态是您需要处理并确保正确的事情。一个grain的状态可以部分地更新,或者那些可能跨多个grain才能完成的操作,是分部分进行的。

看到grain操作失败后,您可以执行以下一项或多项操作。

  • 只需重试您的操作,特别是,如果它不涉及可能做了一半的任何状态的更改。这是迄今为止最典型的情况。
  • 尝试通过调用一个方法,来修复/重置已部分更改的状态,该方法将状态重置为上次已知的正确状态,或者只是通过调用ReadStateAsync从存储中读取状态。
  • 重置所有相关激活体的状态,并确保所有激活体都处于干净状态。
  • 使用Process Manager或数据库事务,执行多grain的状态操作,以确保完全完成或不更改任何内容,以避免状态的部分更新。

根据您的应用程序,重试逻辑可能遵循简单或复杂的模式,您可能必须执行其他操作,例如通知外部系统和其他东西,但一般情况下,您要么重试操作,重新启动所涉及的grain,要么停止响应,直到某个不可用的东西变为可用。

如果您有一个grain,它负责数据库保存而数据库不可用,那么您只需使任何请求失败,直到数据库重新联机。如果您的操作可以根据用户的意愿重试,例如在一个注释grain中保存注释失败了,则可以在用户按下重试按钮时重试(直到一定次数,以避免网络饱和)。具体的细节是特定于具体应用程序的,但是可能的策略是相同的。

策略参数和选择一个好的策略

如上一节所述,您选择的策略取决于应用程序和上下文。策略通常具有必须在应用程序级别决定的参数。例如,如果没有其他进程依赖于某个操作,那么您可能决定每分钟最多重试该操作5次,直到最终完成为止。但是,在处理来自一个用户的任何其他请求之前,您必须处理该用户的登录grain的请求。如果登录动作失败,则无法继续。

Azure文档中有一个关于云的良好模式和实践的指南,在大多数情况下,也适用于Orleans。

一个相当复杂的例子

因为在Orleans中grain是自动激活和停用的,而你并不处理它们的生命周期,所以你通常要处理的仅仅是:确保grain状态是正确的,动作有按彼此的关系,正确地开始和完成。了解grain之间的依赖关系,以及它们所执行的动作,是了解如何处理任何的复杂系统中的故障的重要一步。如果你需要存储grain之间的关系,你可以简单地做到这一点,这也是一个广受遵循的实践。

举个例子,假设我们有一个GameManager grain,它可以启动和停止Game gain,并向游戏中添加Player grain。如果我的GameManager grain无法执行有关启动游戏的操作,那么属于它的相关游戏,也将无法执行其Start(),而Manager可以通过执行编排,来为游戏做到这一点。在Orleans管理内存是自动的,系统会处理它,你只需要确保游戏开始,且Manager可以执行它的Start()。您可以通过以顺序的方式调用相关的方法,或并行调用这些方法,并在其中任何一个方法失败时,重置所有相关的grain的状态,来实现这一点。

如果其中一个game接到一个调用,它将自动重新激活,所以如果你需要用Manager管理game grain,那么所有与管理相关的对game的调用,都应该通过GameManager进行。如果您需要在grain之间进行编排,Orleans并不会为您“自动”编排,需要您自己进行编排。但事实上,你不处理创建/销毁grain,意味着你不需要担心资源管理。您不需要回答以下任何问题:

  • 我应该在哪里创建监督树?
  • 我应该注册哪些grain,以便可以通过名称进行引用?
  • grain X是否存活,我才可以发送消息?
  • ...

所以,游戏开始的例子可以总结如下:

  • GameManager要求Game grain开始
  • Game grain将Player grain添加到自身
  • Game要求Player grain为它们自己添加游戏
  • Game 将其状态设置为启动。
  • GameManager 将游戏添加到其游戏列表中。

现在,如果一个玩家未能将游戏添加到自身,您就不需要杀死所有玩家和游戏,然后重新开始。您只需重置该游戏中加入了自己的其他玩家的状态,再重置GameGameManager的状态(如果需要),然后重新开始你的工作,或宣布失败。如果您可以稍后处理将游戏添加到玩家,您可以在提醒器中继续重试,或在游戏的其他调用(例如游戏的Finish()方法)中重试。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值