gpt4 book ai didi

c# - 在流水线执行中确保 Orleans 中的消息顺序

转载 作者:太空宇宙 更新时间:2023-11-03 22:42:07 25 4
gpt4 key购买 nike

我有三个 Cereal (A、B 和 C)在管道中执行不同的工作。 GrainA 将结果传递给 grainB,grainB 将结果传递给 grainC。我想保证可以通过下面实现的连续 Cereal 之间的顺序消息发送。

// client code
foreach(var i in list)
{
await grainA.job(i);
}

//grain A code
async Task job(var i)
{
DoSomeWorkA(i);
await grainB.job(i);
}

//grain B code
async Task job(var i)
{
DoSomeWorkB(i);
await grainC.job(i);
}

//grain C code
async Task job(var i)
{
DoSomeWorkC(i);
Console.WriteLine(i);
}

但是,这段代码的问题是没有流水线。仅当当前对象遍历所有 grainB 和 grainC 时(由于 await 语句),grainA 才会获得 net 对象。获得流水线的一种方法是不使用 await 并直接一个接一个地发送对象。但是,如 this post 中所述,这会导致无序交付.

我想让执行完全流水线化,这意味着当 grainB 收到来自 grainA 的结果时,grainA 继续它的下一个工作。但是,消息排序也很重要,因为我发送了一些控制消息。如何在奥尔良做到这一点?

最佳答案

为了使高并发系统易于编程和推理,Orleans 将每个 grain(计算单位和状态)的并行度和并发度限制为 1。这意味着最多同时处理一条消息,并且大多数线程将在任何时间点执行给定的 grain 激活代码。

这极大地简化了开发人员需要关注的事情,因为不再需要像锁这样的线程同步原语。

但是,行为是可配置的。如果您不想要这种默认的“安全”行为,那么您可以在 grain 的界面上将 grain 标记为 [Reentrant] 或将单个方法标记为 [AlwaysInterleave]

这允许同时处理许多消息。在 grain 方法中的每个 await 点,执行都返回给调度程序,调度程序可以开始处理另一条消息。调度程序仍然确保每个 grain 激活的单线程性,因此仍然不需要锁,但允许消息在那些 await 点交错(即,协作多任务处理)。这意味着开发人员现在需要考虑这些 await 点之间的其他请求如何改变内部状态。

有关详细信息,请参阅 Reentrancy page in the Orleans documentation .

为了增加并行度(对于 CPU 密集型任务),开发人员可以使用 Stateless WorkersExternal Tasks通过 Task.Run 或类似方式。

另请注意,无论并发配置如何,从 grain 激活 A 发送到 grain 激活 B 的消息将始终按顺序发送。对于从 B 发送到 A 的结果也是如此。请注意,一旦并发性增加,仍然很难推断消息的顺序,但是,因为对 B 的第二次调用可能在第一次调用之前完成,因此其结果将更早发送,还。这意味着结果可能看起来是乱序接收的。不过,我想这就是您所期望的。

关于c# - 在流水线执行中确保 Orleans 中的消息顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51680591/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com