嵌套请求的正确模式
本文关键字:模式 请求 嵌套 | 更新日期: 2023-09-27 18:11:37
我有一个actor,它有许多个子节点,我正在查询它以获得其子节点中的数据聚合。此操作可能需要几秒钟。
我正准备这么做,感觉完全错了。句柄方法由Ask<>
调用。
public void Handle(Message message)
{
var children = Context.GetChildren();
var tasks = new List<Task<Result>>();
foreach (var child in children)
{
var t = child.Ask<Result>(new Query);
tasks.Add(t);
}
Task.WaitAll(tasks.ToArray()); // Gah!
// do some work
Sender.Tell(new Response(new Results()));
}
我有一些想法,但我想得到一些输入,因为我真的不想重新发明一个20边轮。
我很担心对Sender
的引用,以及当我最终调用Tell
时它将指向什么,因为它是一个静态调用。
我最终使用了Task.WhenAll
延续,但仍然不相信它是正确的Akka方式-这是这里的重点。我可以让它工作,我只是想知道最佳实践选项
一般来说,Ask
应该只用于与来自外部服务的参与者的通信,几乎从不用于两个参与者之间的通信。这比使用Tell
要贵得多。另一个问题是使用Task.WaitAll
,它实际上阻塞了当前线程,直到所有响应都到达,这也对性能不利,并可能导致死锁。
类似的话题已经在github上讨论过了。
聚合问题的一般解为:
- 为聚合过程创建一个单独的参与者
- 用actor列表初始化它,它应该从actor中收集数据并记住actor,收集到的结果将通知actor。
- 为每个角色发送请求/查询
- 处理每个请求/查询响应,将其聚合在单独的数据结构中,并从等待参与者列表中删除发送者。
- 一旦没有actor等待-发送结果并停止当前actor(负责数据聚合的actor)。
- 附加
ReceiveTimeout
机制,当由于某种原因不是所有参与者都能在合理的时间内响应时-当超时将达到时,您可能返回失败或迄今为止收集的响应列表。
PS:不要使用TypedActor——它对性能也不好,而且会被淘汰。