【问题标题】:Akka.NET query actors efficientlyAkka.NET 有效地查询参与者
【发布时间】:2016-01-30 18:19:16
【问题描述】:

我正在使用 Akka.NET 为生产项目创建概念证明,但我遇到了查询概念理解问题。

情况如下: CoordinatorActor 有数千个Hotel-Actors 的列表。

我想查询所有Hotel-Actors 在特定日期有空房的所有酒店。

当然,我可以通过它们进行查询并发送.Ask<> 请求以获取特定日期。持有所有任务的参考并做一个Task.WhenAll(requests)。但这感觉有点不自然。

或者,我可以一次向所有酒店(ActorSelection 或路由器)发送一条包含特定日期请求的广播消息,但我不知道他们何时所有回复了 @ 987654325@留言。

有没有人建议如何解决这个问题?

【问题讨论】:

  • 你能详细说明一下真实情况吗?这样可以更轻松地推荐合适的解决方案。
  • 场景是一个有很多酒店的预订网站,用户应该在特定日期看到可用的酒店。酒店是否可用的标准是相当复杂和充满活力的。也应该可以进行子选择,例如仅在特定区域内的酒店。
  • 酒店“数据库”是否是 Akka 的好案例?似乎一些普通的数据结构就足够了,而且开销也更少。如果您需要一直询问所有酒店,那么每家酒店的一名演员似乎也值得怀疑。
  • 可用性标准不是静态的,而是基于预订用户的历史和趋势。 Ever HotelActor 可以自己制造这种分歧。

标签: task-parallel-library akka.net


【解决方案1】:

是的,你的感受就在这里。在参与者之间使用 Ask 进行通信被认为是非常低效的 - 主要是因为每个 ask 需要分配单独的消息侦听器。

第一个好问题是:您需要等待他们都回复吗?也许响应可以在它们到来时发出。

如果您需要在回复之前收集所有数据,您需要有一些方法来计算所有消息,以保证其中一些消息仍然处于待处理状态 - 在这种情况下使用 ActorSelection 是不可行的.您需要与每条消息相关联的计数器或标识符列表 - 虽然它们甚至可以是普通数字,但通常IActorRefs 更易于使用。

您可以在下面看到可以为此特定任务创建的 Aggregator 演员的简化示例 - 一旦没有更多消息等待或超时,它将自动返回所有回复,它收到,并自行停止发生了。

class Aggregator<T> : ReceiveActor
{
    private IActorRef originalSender;
    private ISet<IActorRef> refs;

    public Aggregator(ISet<IActorRef> refs)
    {
        this.refs = refs;
        // this operation will finish after 30 sec of inactivity
        // (when no new message arrived)
        Context.SetReceiveTimeout(TimeSpan.FromSeconds(30));
        ReceiveAny(x =>
        {
            originalSender = Sender;
            foreach (var aref in refs) aref.Tell(x);
            Become(Aggregating);
        });
    }

    private void Aggregating()
    {
        var replies = new List<T>();
        // when timeout occurred, we reply with what we've got so far
        Receive<ReceiveTimeout>(_ => ReplyAndStop(replies));
        Receive<T>(x =>
        {
            if (refs.Remove(Sender)) replies.Add(x);
            if (refs.Count == 0) ReplyAndStop(replies);
        });
    }

    private void ReplyAndStop(List<T> replies)
    {
        originalSender.Tell(new AggregatedReply<T>(replies));
        Context.Stop(Self);
    }
}

【讨论】:

  • 感谢完美的答案和代码!事实上,我需要确保所有参与者都返回,否则不能保证结果正确。我发现大量hotelActors(1M)上的Ask确实会导致内存不足异常。我使用数据库查询酒店的标准(面积、星级等)并选择 ActorPath 的字符串(witch 是静态的)。这样,只有相关的 hotelActor 才会被请求以获取可用性。顺便说一句,这段代码对于并行请求可能不安全?
  • 此示例假设您为每个聚合查询创建一个参与者。它会自动倒下。当涉及到正确性保证时,这取决于用例 - 不完整的答案并不总是一个坏答案,即从酒店搜索的角度来看,显示 120 个正确答案中的 100 个仍然比显示红色消息“对不起,我们无法满足您的要求”。
猜你喜欢
  • 1970-01-01
  • 2016-07-14
  • 1970-01-01
  • 1970-01-01
  • 2015-07-21
  • 2015-06-10
  • 2016-08-07
  • 2017-12-21
  • 1970-01-01
相关资源
最近更新 更多