2

我们正在尝试实现重试逻辑以从 Azure 环境中的瞬态错误中恢复。

我们正在使用长时间运行的会话来跟踪并在应用程序事务结束时提交所有更改(可能分布在多个 Web 请求中)。一路上,我们需要从数据库中获取额外的数据。我们的主要问题是我们不能轻易地从 db 错误中恢复,因为我们不能“重播”所有用户操作。

到目前为止,我们使用了简单的恢复算法:

  • 尝试在长时间运行的会话中执行操作
  • 如果出现错误,请关闭会话,打开一个新会话并将实体合并到其中
  • 重试操作

就时间而言,这是非常昂贵的方法(合并对于大型实体层次结构来说真的很长)。所以我们想稍微优化一下。

我们希望在单独的会话中执行查询操作(以保持长时间运行一个未触及和安全),并在成功后将结果合并回长时间运行的会话。重试在这里相对简单——我们只需要打开新会话并再次运行查询。但是,使用这种方法,我们在初始化惰性属性/集合时会遇到问题:

  • 如果我们在单独的会话中执行此操作,我们需要将结果合并回来(很多实体),但合并可能会失败并中断长时间运行的会话
  • 我们尝试了不同的方式将原始实体“移动”到不同的会话,加载详细信息并将其返回,但没有成功(驱逐、复制等)

有一个已知的声明,如果出现异常,会话应该被丢弃。但是,该示例显示了操作。阅读的人仍然如此吗?我的意思是如果我保证没有数据被写回数据库,我可以重复使用同一个会话来再次运行查询吗?

您对长时间运行的会话的重试逻辑还有其他建议吗?

4

1 回答 1

1

IMO 没有办法解决您的问题。提交所有内容将花费大量时间,否则您将不得不做大量工作将其分解为较小的会话并处理合并时可能发生的每个错误。

要回答有关在异常后使用会话的问题:您不能再信任此会话中的任何内容,甚至不能信任已加载的实体。

阅读 Ayende 的文章中关于在会话中出现异常时使用恢复计划构建简单的待办事项应用程序的这一段:

然后是错误处理的问题。如果你得到一个异常(比如 StaleObjectStateException,因为并发冲突),你的 session 和它加载的实体是 toast,因为使用 NHibernate,一个 session 抛出的异常会将该 session 移动到一个未定义的状态。您不能再使用该会话或任何加载的实体。如果您只有一个全局会话,则意味着您可能需要重新启动应用程序,这可能不是一个好主意。

于 2013-06-12T07:26:50.560 回答