带 Azure Table 存储的工作流系统
Workflow System with Azure Table Storage
我有一个系统,我们需要 运行 一个简单的工作流程。
示例:
- 1 月 1 日 08:15 为对象 Z 触发任务 A
- 触发后 运行 一些代码(实现细节不重要)
- 将对象 Z 的任务 B 安排到 运行 在 1 月 3 日 10:25(依此类推)
工作流程本身很简单,但我需要 运行 500.000+ 个实例,这是棘手的部分。
我知道 Windows Workflow Foundation,出于同样的原因,我选择不使用它。
我的初始设计是使用 Azure Table 存储,我非常感谢对设计的反馈。
系统将由两个table
组成
Table "Jobs"
PartitionKey: ObjectId
Rowkey: ProcessOn (UTC Ticks in reverse so that newest are on top)
Attributes: State (Pending, Processed, Error, Skipped), etc...
Table "Timetable"
PartitionKey: YYYYMMDD
Rowkey: YYYYMMDDHHMM_<GUID>
Attributes: Job_PartitionKey, Job_RowKey
想法是 运行s table 将拥有每个对象的完整作业历史,Timetable 将拥有所有作业的列表 运行 以后。
一些假设:
- 一项工作永远不会跨越一个以上的对象
- 每个对象只会有一个待处理的作业
- "job" 非常轻量级,例如将消息发布到队列
系统必须能够执行这些任务:
执行挂起的作业
- 用 "partition <= Today" 和 "RowKey <= today"
查询 "Timetable" 中的所有记录
- 对于每条记录(并行)
- 通过 PartitionKey 和 RowKey 在 Jobs table 中查找作业
- 如果 "not exists" 或 State != Pending 然后跳过
- 执行"logic"。如果失败=>记录并可能做一些重试逻辑
- 提交"Next run date in Timetable"
- 将 "Update State = Processed" 和 "New Job Record (next run)" 作为单个事务提交
- 全部完成后 => 删除所有已处理的 Timetable 条记录
关注:三个记录修改中只有两个在一个事务中。这可以通过任何方式克服吗?
停止工作流
Stop/pause 对象 Z 的工作流程
- 按 PartitionKey
查询作业 table 中的前 1 个作业
- 如果有任何 AND State == Pending 然后更新为 "Cancelled"
- (无需打扰清理时间table它会自行清理"when time comes")
开始工作流程
- 在作业中创建待定记录table
- 及时创建记录table
在"executing the thing"方面我会
使用 Azure Functions 或 Scheduler-thing 每 5 分钟左右执行一次挂起的作业。
如有任何意见或建议,我们将不胜感激。
谢谢!
改用服务总线怎么样? BrokeredMessage class 有一个名为 ScheduledEnqueueTimeUtc 的 属性。您可以通过 ScheduledEnqueueTimeUtc 属性 安排您希望作业 运行 的时间,然后 fuggedabouddit。然后,您可以有一个触发的 web 作业来监视服务总线消息队列,并且将在作业消息排队时被触发。我非常喜欢依靠现有服务来最大限度地减少所需的编码。
我有一个系统,我们需要 运行 一个简单的工作流程。 示例:
- 1 月 1 日 08:15 为对象 Z 触发任务 A
- 触发后 运行 一些代码(实现细节不重要)
- 将对象 Z 的任务 B 安排到 运行 在 1 月 3 日 10:25(依此类推)
工作流程本身很简单,但我需要 运行 500.000+ 个实例,这是棘手的部分。
我知道 Windows Workflow Foundation,出于同样的原因,我选择不使用它。
我的初始设计是使用 Azure Table 存储,我非常感谢对设计的反馈。
系统将由两个table
组成Table "Jobs"
PartitionKey: ObjectId
Rowkey: ProcessOn (UTC Ticks in reverse so that newest are on top)
Attributes: State (Pending, Processed, Error, Skipped), etc...
Table "Timetable"
PartitionKey: YYYYMMDD
Rowkey: YYYYMMDDHHMM_<GUID>
Attributes: Job_PartitionKey, Job_RowKey
想法是 运行s table 将拥有每个对象的完整作业历史,Timetable 将拥有所有作业的列表 运行 以后。
一些假设:
- 一项工作永远不会跨越一个以上的对象
- 每个对象只会有一个待处理的作业
- "job" 非常轻量级,例如将消息发布到队列
系统必须能够执行这些任务:
执行挂起的作业
- 用 "partition <= Today" 和 "RowKey <= today" 查询 "Timetable" 中的所有记录
- 对于每条记录(并行)
- 通过 PartitionKey 和 RowKey 在 Jobs table 中查找作业
- 如果 "not exists" 或 State != Pending 然后跳过
- 执行"logic"。如果失败=>记录并可能做一些重试逻辑
- 提交"Next run date in Timetable"
- 将 "Update State = Processed" 和 "New Job Record (next run)" 作为单个事务提交
- 全部完成后 => 删除所有已处理的 Timetable 条记录
关注:三个记录修改中只有两个在一个事务中。这可以通过任何方式克服吗?
停止工作流 Stop/pause 对象 Z 的工作流程
- 按 PartitionKey 查询作业 table 中的前 1 个作业
- 如果有任何 AND State == Pending 然后更新为 "Cancelled"
- (无需打扰清理时间table它会自行清理"when time comes")
开始工作流程
- 在作业中创建待定记录table
- 及时创建记录table
在"executing the thing"方面我会 使用 Azure Functions 或 Scheduler-thing 每 5 分钟左右执行一次挂起的作业。
如有任何意见或建议,我们将不胜感激。
谢谢!
改用服务总线怎么样? BrokeredMessage class 有一个名为 ScheduledEnqueueTimeUtc 的 属性。您可以通过 ScheduledEnqueueTimeUtc 属性 安排您希望作业 运行 的时间,然后 fuggedabouddit。然后,您可以有一个触发的 web 作业来监视服务总线消息队列,并且将在作业消息排队时被触发。我非常喜欢依靠现有服务来最大限度地减少所需的编码。