COM+ CRM 操作过程

在正常操作中,在服务器应用程序进程中运行的应用程序组件将创建 CRM 工作器来使用 COM+ CRM。 CRM 工作器实现特定于其旨在执行的任务的 COM 接口。 应用程序组件必须在事务下运行,以便 CRM 工作器继承应用程序组件的事务。 CRM 工作器始终需要事务。

若要访问 COM+ CRM,CRM 工作器应先获取 ICrmLogControl 接口,该接口允许 CRM 工作器将记录写入持久日志。 CRM 工作器将创建 CRM 分配器组件来获取此接口。

接下来,CRM 工作器必须告诉 CRM 分配器要使用的 CRM 补偿程序的名称。 为此,将调用 ICrmLogControl::RegisterCompensator 方法。 调用此方法后,在事务完成时 CRM 基础结构将创建 CRM 补偿程序。

在 CRM 工作器注册其 CRM 补偿器后,可以使用 ICrmLogControl 将记录写入 CRM 日志。 CRM 工作器必须预写;也就是说,它必须将记录写入日志,以在实际执行操作之前描述操作,以防在完成操作后立即发生崩溃。 如果没有这些预写日志记录,则无法更正操作。

此外,预写意味着 CRM 补偿程序(在恢复时接收日志记录的组件)必须处理已写入日志记录但实际上未执行操作的情况。 CRM 补偿程序的操作必须是幂等操作;也就是说,它们应该能够多次执行,但应产生相同的结果。 例如,将帐户余额设置为值 $100 是幂等操作;将 $100 添加到帐户余额不是。

ICrmLogControl 接口提供以下两种写入日志记录的方法:

  • WriteLogRecordVariants 用于写入生成为 Variants 集合的结构化日志记录。 它主要用于在 Microsoft Visual Basic 中开发 CRM。
  • WriteLogRecord 用于将非结构化日志记录作为字节的 BLOB 写入。 它主要用于在 Microsoft Visual C++ 中开发 CRM。 由于 C 中的记录结构通常由一组可能分散在内存中的标头和字段组成,因此 WriteLogRecord 方法会实现可减少数据复制的收集功能。

注意

不应在日志记录的数据结构中使用指针类型。 指针在恢复阶段不再有效,因为 CRM 补偿程序在与写入日志记录的 CRM 工作器不同的进程中运行。 在日志记录中包含指针类型时,可能会导致应用程序在恢复过程中崩溃或损坏。

 

这两种写入方法都会将日志记录写入磁盘,但不能保证记录的持久性。 虽然在强制写入磁盘之前能够累积延迟写入可以提高性能,但可以改用 ICrmLogControl::ForceLog 方法,以确保 CRM 执行的所有写入在磁盘上都是持久的,这对于故障恢复非常重要。

当 CRM 工作器完成其操作并完成将记录强制写入日志时,它必须释放 ICrmLogControl。 事务完成后(通常是由于应用程序组件调用 SetCompleteSetAbort),CRM 基础结构将创建 CRM 补偿程序组件,该组将件实现 ICrmCompensator 接口或 ICrmCompensatorVariants 接口。 这些接口用于将非结构化 (Visual C++) 或结构化 (Visual Basic) 记录与事务结果通知一起传递到 CRM 补偿程序。

CRM 补偿程序会先收到事务完成准备阶段的通知,并且可以对准备请求投下 yes 或 no。 如果 CRM 补偿程序投下 no,则不会收到任何其他中止通知。 如果对准备请求投下 yes,则会收到提交通知或中止通知。 对于客户端中止,不会收到任何准备通知,仅收到中止通知。 CRM 补偿程序必须准备好处理所有这些情况,并且还必须处理 CRM 工作器未成功写入任何日志记录的情况。 CRM 补偿程序不得假定同一 CRM 补偿程序实例将同时收到阶段 1(准备)和阶段 2(提交或中止)通知,因为这些通知可能会被恢复中断。

通常,CRM 补偿程序使用中止通知来反转 CRM 工作器执行的操作。 如果 CRM 工作器需要反转其操作,则 CRM 工作器可能会保留某个状态可用。 该状态可能完全包含在日志记录中,如果没有,CRM 补偿程序需要在事务提交时清理该状态。 这是 CRM 补偿程序收到提交通知的原因。 CRM 补偿程序不会在 DTC 事务下运行。

如果需要,CRM 补偿程序可以使用 ICrmLogControl 记录新记录,该记录是在创建时收到的。 CRM 工作器和 CRM 补偿程序还可以忘记他们写入的最后一条日志记录,这可能是避免不必要的恢复所需。

COM+ 补偿资源管理器概念

COM+ CRM 启动和恢复