【问题标题】:Suspend Akka Actors暂停 Akka 演员
【发布时间】:2012-10-14 17:47:35
【问题描述】:

我正在尝试使用 Akka 来实现以下内容(我想我正在尝试以正确的方式使用 Akka):

我有一个系统,其中有 n 个资源侦听器。本质上,资源侦听器是一个实体,它将侦听输入资源并发布它所看到的内容(即轮询数据库、跟踪日志文件等)。

所以我想使用 Akka 演员来完成这些小工作单元(监听资源)。我注意到 Akka 给了我一个 t 线程的线程池,它可能少于侦听器的数量。对我来说不幸的是,从这些资源侦听器获取消息可能会阻塞,因此可能需要几秒钟、几分钟才能弹出下一条消息。

有没有办法暂停资源侦听器,以便将线程留给另一个参与者,我们稍后再讨论它?

【问题讨论】:

  • 您可以编写一个 ping 资源侦听器并让侦听器休眠直到收到 ping 的 actor。
  • 您是否打算在集合中显式注册 侦听器,并从您的资源代码中显式调用它们,例如在每个对象上调用 fireResourceEvent输入发布了一些东西?
  • 好吧,实际的资源逻辑更像是对资源的轮询,即在资源对象上调用 getMessage() 方法,然后发布该消息。所以resourceListener有-一个资源,不像resource listener是由resource通知的。

标签: scala blocking akka


【解决方案1】:

执行摘要

您希望您的生产者 API(资源)是异步的,或者至少支持非阻塞操作(以便您可以进行轮询)。如果 API 不支持,那么就没有办法改造这个属性,甚至不使用全能的演员 ;-)

针对不同情况的策略

仅阻塞 API

如果资源仅支持阻塞getWhatever() 检索事物的方法,那么您必须为每个资源分配一个线程。带有 PinnedDispatcher 的 Actor 可能是实现此目的的一种方式。但请注意,actor 在等待来自资源的事件时不会做出响应。

非阻塞但同步的 API

如果资源 API 上有 peek()poll() 方法,您可以为每个资源使用一个参与者,让它们共享一个线程(或池)并根据需要安排轮询(即每 100 毫秒或任何您需要的时间)需要)。这具有巨大的优势,即实际上没有人被阻止并且整个系统保持响应。但是事件接收的延迟将是您的计划间隔的顺序。

适当的异步 API

如果你有足够好的因果报应遇到一个不错的异步 API,那么只需注册一个回调,它会在事件发生时向参与者发送消息。可悲的是,这不是常态。

PS:

JVM 不支持包装当前调用堆栈、执行其他操作并稍后返回相同的处理状态。方法只有在实际完成后才能出栈。

【讨论】:

    【解决方案2】:

    一般来说,您应该尽量避免在actors中阻塞操作。对于文件 IO,有异步库,对于一些数据库也有。如果这不适合您,您可以设置更改默认调度程序,以便根据需要扩展底层线程池。

    【讨论】:

    • 调度器还是调度器?似乎 PinnedDispatcher 有一个线程每个actor。
    • 我的意思是调度员。改了。
    • PinnedDispatcher 似乎不是一个好主意,这就像为每个侦听器专门分配一个线程来轮询,在我看来这与您想要实现的目标相反。
    • @pagoda_5b:这就是为什么我说非阻塞IO更可取
    • 我还会在 Scala 2.10 中查看 Futures 文档中的 Blocking 段落
    【解决方案3】:

    一种选择是在 Futures 中调用阻塞 API。 Futures 应该使用与 Actor 的 ExecutionContext 分开的 ExecutionContext(线程池)。

    请参阅this blog post 获取示例(特别是 CacheActor.findValueForSender)。

    【讨论】:

      猜你喜欢
      • 2019-01-01
      • 2015-05-06
      • 1970-01-01
      • 2014-03-09
      • 2019-01-16
      • 2015-03-25
      • 1970-01-01
      • 1970-01-01
      • 2019-04-23
      相关资源
      最近更新 更多