1

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

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

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

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

4

3 回答 3

3

执行摘要

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

针对不同情况的策略

仅阻塞 API

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

非阻塞但同步的 API

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

适当的异步 API

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

PS:

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

于 2012-10-25T09:34:07.337 回答
0

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

于 2012-10-24T16:48:29.000 回答
0

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

有关示例(特别是 CacheActor.findValueForSender),请参阅此博客文章。

于 2012-10-25T13:55:23.487 回答