微软奥尔良粒子通信性能

3
我正在使用Microsoft Orleans作为基础构建一个工作流引擎,因为它提供了许多有用的功能,例如自动分配工作和处理故障转移。我有三种类型的grains:
- 工作流:保存工作流程信息以及应该执行工作块的顺序。 - 工作块:实际执行工作的部分。 - 执行:工作流程的单个执行。
我的问题是,当运行大量的当前执行(即> 1000)时,性能真的很差。我已经进行了一些分析,并将其缩小到grains之间发生的通信。是否有任何进一步改进的方法?以下是我的代码概要及grains相互作用:
执行grain在循环中等待下一个工作块并调用工作块的execute。正是这种grains之间的不断调用导致了其中一个测试工作流的执行时间从单次执行10秒增加到超过1000次执行时约5分钟。这可以改善吗,或者应该重新设计解决方案以消除grain通信?
[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();
        ...
    }
}

也许是 [PreferLocalPlacement]? - BozoJoe
2个回答

7

以下有几个问题:

1)工作流(Workflow)既是StatelessWorker,又使用StorageProvider不太对。StorageProvider意味着它具有需要持久化的状态,而StatelessWorker则表示它没有任何状态。建议使用常规的非StatelessWorker颗粒。

2)从上到下看模型:Workflow只是有关工作流程和执行代码的数据,WorkBlock是多块工作流程中的一块(多步工作流程的一步),对吗?在这种情况下,它们都不应该是颗粒。它们只是状态。Execution是唯一需要颗粒的部分。Execution接收Workflow,Workflow在其数据中编码了下一个块是什么,而Execution只是执行该块。

3)从可扩展性的角度来看,您只需要大量的Execution颗粒。如果一个Workflow有一个ID,那么您可以为每个Workflow ID使用一个Execution颗粒。如果要并行多次执行相同的Workflow(具有相同的ID),则现在取决于情况。如果不是太多并行,也许一个Execution颗粒就足够了。如果不是,您可以使用X个Execution颗粒的池(Execution颗粒的ID将是"WorkflowId-NumberBetween0AndX")。


1
在我看来,这些功能不应该是独立的颗粒,将它们聚合起来可以消除昂贵的颗粒间通信。
如果将“工作块”重命名为“活动”,将“执行”重命名为“工作流程实例”,那么您的概念就非常类似于微软的工作流基础。我已经在GitHub上启动了一个项目(Orleans.Activities),以在Orleans上运行WF4工作流。虽然它还没有准备好投入生产,也没有性能测试,但至少可以工作。也许你应该试一试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接