2012-09-28 41 views
7

我想调用一个数据库,其中有大量数据,可能需要一段时间才能返回。Play&Akka并阻止数据库访问的线程

我打算在调用Akka.future(f)的过程中完成这项工作,并在工作完成时使用Async {}来呈现响应。

这样做是否有意义,还是应该在控制器中进行长数据库调用,而不将工作发送给Akka?

或者有没有办法做非阻塞数据库访问?

回答

1

如果响应在完成数据库调用时被阻止,那么只有在调用运行时组装响应时完成其他工作才能使其异步。

非阻塞数据库访问可能意味着两件事情:客户端库为您提供基于回调的API,与未来的解决方案非常相似,或者使用非阻塞套接字来保存线程使用情况。我假设你是指前者,在这种情况下,我认为它在功能上等同于使用未来。

+0

数据库调用块和我没有其他工作要做的传入请求。但Play服务器本身可以同时处理另一个传入的请求。但是,如果我将工作发送到Akka.future(工作),那么它的处理由处理任何新的传入请求的相同线程处理,所以我认为通过传递Akka并不会产生任何区别。事实上,它甚至可能会导致额外的开销。那有意义吗? –

+1

是的,我认为这是有道理的。假设在数据库调用中阻塞IO,它将占用一个线程直到它完成。我不太了解Play,但这不应阻止任何合理的Web框架为其他请求提供服务。在等待来自数据库服务器的数据包时,可以在CPU上调度其他线程,就像任何其他应用程序一样,Play应该有一个可用的线程池。如果这是有道理的,接受答案。 =) – spieden

2

您可以使用Akka.future(f)并提供您自己的Akka配置文件以获取更多线程来处理您的数据库访问。例如,看this config file

但你指出:真正的问题是在使用阻塞的数据库驱动程序。我不知道你正在使用哪个数据库,但是值得看一下MongoDB,例如ReactiveMongo。使用ReactiveMongo,所有的MongoDB操作都是非阻塞和异步的。有一个很好的介绍here。此外,它与Play Framework非常相称(查看ReactiveMongo Play Plugin)。

编辑:您还可以检查“Configuring Playframework's internal Akka system”来调整工作线程编号。

+0

我被困在MySQL ...,但它似乎也有一个异步API呢!该配置文件是否有文档? –

+0

由于此配置文件实际上是用于Akka的,因此您可以阅读[Akka配置文档](http://doc.akka.io/docs/akka/2.0.3/general/configuration.html)。 –

+0

我忘了提这个[doc](http://www.playframework.org/documentation/2.0。3/AkkaCore)([配置Playframework的内部Akka系统](http://www.playframework.org/documentation/2.0.3/AkkaCore))。 –

4

如果您不得不为数据库使用阻塞驱动程序(如果出于某种原因,MySQL的异步驱动程序无法正常工作),请考虑使用PinnedDispatcher设置Actor池(使用路由)。

PinnedDispatcher为每个参与者提供一个线程,并通过设置路由器,使您能够调整严格负责处理数据库调用的线程数。轻松缩放。另外,通过使用Actor,你可以在演员之间构造消息(例如,具有数据库调用结果的消息)更容易一些。