我正在开发一个以Mircosoft Orleans为基础的工作流引擎,因为它提供了许多有用的功能,如自动分配工作和处理故障转移。
我有三种类型的谷物:
- 工作流-保存工作流中的信息以及工作块的执行顺序
- 工作块-实际完成工作的部件
- 执行-工作流的单一执行
我的问题是,当运行大量当前执行(即>1000)时,性能确实会受到影响。我已经做了一些分析,并将其缩小到谷物之间发生的通信。我还有什么可以改进的吗?
以下是我的代码概要以及颗粒如何与相互作用
执行粒度位于一个循环中,从工作流中获取下一个工作块,然后在该工作块上调用execute。正是这种颗粒之间的不断调用导致我的一个测试工作流的执行时间从运行单个执行时的10秒增加到运行超过1000时的5分钟左右。这一点可以改进吗?或者我应该重新设计解决方案以删除谷物通信吗?
[StorageProvider(ProviderName = "WorkflowStore")]
[Reentrant]
[StatelessWorker]
public class Workflow : Grain<WorkflowState>, IWorkflow
{
public Task<BlockRef> GetNext(Guid currentBlockId, string connectionName)
{
//Lookup the next work block
}
}
[Reentrant]
[StatelessWorker]
public class WorkBlock : Grain<WorkBlock State>, IWorkBlock
{
public Task<string> Execute(IExecution execution)
{
//Do some work
}
}
[StorageProvider(ProviderName = "ExecutionStore")]
public class Execution : Grain<ExecutionState>, IExecution, IRemindable
{
private async Task ExecuteNext(bool skipBreakpointCheck = false)
{
if (State.NextBlock == null)
{
await FindAndSetNext(null, null);
}
...
var outputConnection = await workblock.Execute();
if (!string.IsNullOrEmpty(outputConnection))
{
await FindAndSetNext(State.NextBlock.Id, outputConnection);
ExecuteNext().Ignore();
}
}
private async Task FindAndSetNext(Guid? currentId, string outputConnection)
{
var next = currentId.HasValue ? await _flow.GetNextBlock(currentId.Value, outputConnection) : await _flow.GetNextBlock();
...
}
}
这里有几个问题:
1) 工作流是一个无状态的Worker并使用StorageProvider似乎是不对的。StorageProvider意味着它具有它关心的状态,而StatelessWorker意味着它没有任何状态。相反,使用常规的非StatelessWorker谷物。
2) 让我们从上往下看建模:工作流只是关于工作流和要执行的代码的数据,WorkBlock是多块工作流的一个块(多步工作流的一步),对吗?在这种情况下,它们都不应该是谷物。他们只是国家。执行是唯一需要颗粒的。Execution接收工作流,工作流在其数据中编码下一个块,Execution只执行该块。
3) 从可伸缩性的角度来看,您只需要大量的执行粒度。如果一个工作流有一个id,那么你可以为每个工作流id使用一个执行粒度。如果你想并行多次执行同一个工作流(具有相同id),现在就取决于它了。如果并行性不太高,也许一个执行粒度就足够了。如果没有,您可以使用X个执行粒度的池(执行粒度的id将是"WorkflowId-NumberBetween0AndX")。
在我看来,这些函数不应该是独立的粒度,聚合它们将消除昂贵的粒度间通信。
如果将工作块重命名为活动,将Execution命名为WorkflowInstance时,您的概念将与Microsoft的Workflow Foundation非常相似。我在GitHub(Orleans.Activities)上启动了一个项目,在Orleans上运行WF4工作流。虽然它还没有准备好生产,也没有性能测试,但至少可以工作。也许你应该试一试。