使用 InstanceLockedExceptionAction SQL 工作流实例存储的属性可以指定 SQL 持久性提供程序在收到 InstanceLockedExceptionSQL 暂留提供程序时应执行的操作。 当持久性提供程序尝试锁定当前被另一个服务主机锁定的工作流服务实例时,它会收到此异常。 此属性的值是 NoRetry, BasicRetry和 AggressiveRetry。 默认值为 NoRetry。 以下列表描述了三个选项:
NoRetry。 服务主机不会尝试锁定工作流服务实例并传递给 InstanceLockedException 调用方。 如果工作流在内存中停留超过 60 秒的时间,请使用 NoRetry 重试。 默认值为 NoRetry。
BasicRetry。 服务主机重新尝试以在重试尝试之间以线性间隔锁定工作流服务实例,并将调用方传递到 InstanceLockedException 序列末尾的调用方。 如果工作流在大约 5-60 秒之间保留在内存中,并且消息会成批到达,其中消息更有可能发送到同一主机上的同一实例以处理所有消息,然后再卸载工作流,从而在 BasicRetry 不使用浪费资源的情况下实现最佳延迟。
AggressiveRetry。 服务主机重新尝试以指数退避间隔锁定工作流服务实例,并将异常传递给序列末尾的调用方。 如果工作流在内存中停留的时间非常短(小于 5 秒),或者 Web 场很大,并且将另一条消息传送到同一主机的可能性并不高,则用于 AggressiveRetry 实现最佳延迟。
实例锁定异常操作功能支持以下方案。 在所有方案中,如果 SqlWorkflowInstanceStore 的 instanceLockedExceptionAction 属性设置为 BasicRetry 或 AggressiveRetry设置为,则主机会以透明方式重试以定期获取实例上的锁。
启用正常关闭和应用程序域的重叠回收。 假设正在运行工作流服务实例的服务主机的 AppDomain 正在回收,并且会启动新的 AppDomain 以并行处理新请求,而旧的 AppDomain 则正常关闭。 关闭会等待工作流服务实例处于空闲状态,然后持久保存并卸载实例。 新 AppDomain 中主机锁定实例的任何尝试都将导致一个 InstanceLockedException。
跨同质服务器场水平缩放持久工作流。 假设运行工作流实例的服务器场的节点崩溃,工作流主机无法删除正在运行的实例上的锁。 当在场的另一个节点上运行的服务主机收到该工作流实例的消息时,它会尝试获取这些实例上的锁,它将接收该 InstanceLockedException消息。 锁将在一段时间后过期,因为应该续订锁的主机不再存在。
跨同质服务器场水平缩放持久工作流。 假设你想要使用 NLB(网络负载均衡器)后面的多个主机水平缩放持久工作流,该工作流主机在场的一个节点上运行并正在处理一条消息,并且该实例的下一条消息将路由到在另一个节点上运行的主机,因为 NLB 没有路由算法将消息传送到正在运行实例的主机。 收到消息后,第二个主机会尝试加载工作流实例并接收 InstanceLockedException 该消息,因为第一个主机对实例有锁。 第一个主机在处理完第一条消息后解锁实例,第二个主机在下一次重试时获取锁,加载实例并处理第二条消息。