本文档介绍与工作流持久性相关的工作流设计和配置的最佳做法。
持久工作流的设计和实施
通常,工作流在短时间内执行任务,这些任务与工作流因等待事件而处于空闲状态的时间交替进行。 此事件可以是消息或过期计时器等。 若要能够在工作流实例空闲时卸载工作流实例,服务主机必须保留工作流实例。 仅在工作流实例未位于非持久性区域中时(例如,等待事务完成或等待异步回调)可能出现此情况。 若要允许空闲的工作流实例卸载,工作流设计者应仅在短期操作中使用事务范围和异步活动。 具体而言,作者应尽可能缩短延迟活动在这些非持久性区域中的保留时间。
仅当工作流使用的所有数据类型都是可序列化的时,才能持久保存工作流。 此外,持久化工作流中使用的自定义类型必须可 NetDataContractSerializer 序列化,以便由 SqlWorkflowInstanceStore持久化。
如果主机或计算机失败,如果工作流实例尚未持久保存,则无法恢复该实例。 一般情况下,我们建议在工作流生命周期的早期保留工作流实例。
如果工作流长时间繁忙,建议在整个繁忙时段定期持久化工作流实例。 为此,可以在整个活动序列中添加 Persist 活动,使工作流实例保持忙碌。 通过这种方式,应用程序域回收、主机故障或计算机故障不会导致系统回滚到繁忙时段的开始。 请注意,将活动添加到 Persist 工作流可能会导致性能下降。
Windows Server App Fabric 极大地简化了持久性的配置和使用。 有关详细信息,请参阅 Windows Server App Fabric 持久性
可伸缩性参数的配置
可伸缩性和性能要求确定以下参数的设置:
根据当前方案,应按如下所示设置这些参数。
方案:需要最佳响应时间的少量工作流实例
在此方案中,所有工作流实例在空闲时应保持加载状态。 将 TimeToUnload 设置为较大值。 使用此设置可防止工作流实例在计算机之间移动。 仅当以下一个或多个为 true 时,才使用此设置:
工作流实例在其整个生存期内接收单个消息。
所有工作流实例都在单个计算机上运行
工作流实例接收的所有消息都由同一台计算机接收。
使用 Persist 活动或设置为 TimeToPersist 0,以便在服务主机或计算机发生故障后恢复工作流实例。
场景:工作流实例长时间处于空闲状态
在此方案中,设置为 TimeToUnload 0 以尽快释放资源。
方案:工作流实例在短时间内接收多个消息
在此方案中,如果这些消息由同一台计算机接收,则设置为 TimeToUnload 60 秒。 这可以防止快速卸载和加载工作流实例。 这也不会使实例在内存中保留太久。
将 TimeToUnload 设置为 0,如果这些消息可能会被不同的计算机接收,则将 InstanceLockedExceptionAction 设置为 BasicRetry 或 AggressiveRetry。 这样,工作流实例就可以由另一台计算机加载。
场景:工作流使用持续时间较短的延迟活动
在此方案中,SqlWorkflowInstanceStore 定期轮询持久性数据库,以查找因活动 Delay 过期而需要加载的实例。 如果 SqlWorkflowInstanceStore 找到将在下一轮询间隔过期的计时器,SQL 工作流实例存储会缩短轮询间隔。 之后,下一次轮询将在计时器过期后发生。 这样,SQL 工作流实例存储对于运行时间超过由 RunnableInstancesDetectionPeriod 设定的轮询间隔的计时器实现了高度的精确度。 若要启用较短延迟的及时处理,工作流实例必须至少在内存中保留一个轮询时间间隔。
设置为 TimeToPersist 0 以将过期时间写入持久性数据库。
将TimeToUnload设置为大于或等于RunnableInstancesDetectionPeriod,以确保至少一个轮询间隔将实例保留在内存中。
我们不建议减少 RunnableInstancesDetectionPeriod ,因为这样会导致持久性数据库的负载增加。 每个使用 SqlWorkflowInstanceStore 的服务主机在每个检测周期内轮询数据库一次。 服务主机数量较多时,设置 RunnableInstancesDetectionPeriod 为过短的时间间隔可能降低系统性能。
配置 SQL 工作流实例存储
SQL 工作流实例存储具有以下配置参数:
InstanceEncodingOption
此参数指示 SqlWorkflowInstanceStore 压缩工作流实例状态。 压缩可减少存储在持久性数据库中的数据量,并减少持久性数据库驻留在专用数据库服务器上的网络流量。 如果使用压缩,则需要计算资源来压缩和提取实例状态。 在大多数情况下,压缩会提高性能。
InstanceCompletionAction
此参数指示 SqlWorkflowInstanceStore 保留或删除已完成的实例。 保留已完成的实例会增加持久性数据库存储要求,并导致较大的表,这会增加表查找时间。 除非调试或审核需要已完成的实例,否则最好指示 SqlWorkflowInstanceStore 删除已完成的实例。 仅当用户建立最终删除这些实例的过程时,才应保留已删除的实例。 请注意,只要已完成的工作流实例驻留在实例存储中,则无法重复使用相关密钥。
RunnableInstancesDetectionPeriod
此参数定义在SqlWorkflowInstanceStore活动过期时,Delay轮询持久性数据库以加载相关实例的最大间隔。 SqlWorkflowInstanceStore如果发现将在下一轮询间隔过期的计时器,则会缩短轮询间隔,以便在计时器过期后立即进行下一次轮询。 这样,SQL 工作流实例存储可以实现对运行时间超过 RunnableInstancesDetectionPeriod 的计时器的高精度。
不建议减少RunnableInstancesDetectionPeriod,因为这会导致持久性数据库的负载增加。 每个使用 SqlWorkflowInstanceStore 的服务主机在每个检测周期内轮询数据库一次。 如果服务主机数量较多,将 RunnableInstancesDetectionPeriod 设置为过小的间隔可能会导致系统性能下降。
HostLockRenewalPeriod
此参数定义主机在持久性数据库中续订其锁的间隔。 缩短此间隔后,如果主机或计算机发生故障,工作流实例的恢复速度会更快。 另一方面,短锁续订期会增加持久性数据库的负载。 每个使用 SqlWorkflowInstanceStore 的服务主机将在每个续订期内在数据库中更新一次其锁。 如果计算机运行许多服务主机,请确保锁续订导致的负载不会降低系统的性能。 如果有效,请考虑增加 HostLockRenewalPeriod。
InstanceLockedExceptionAction
如果启用, SqlWorkflowInstanceStore 则重试以在未来 30 秒内加载锁定的实例。 如果工作流在短时间内收到多个消息,并且这些消息由不同的计算机接收,则设置为 InstanceLockedExceptionAction BasicRetry 或 AggressiveRetry。
由于加载重试机制不会引入任何性能开销,只要未尝试负载重试, InstanceLockedExceptionAction 应始终启用。