了解非阻止Web服务调用与非阻止JDBC之间的区别

时间:2014-08-30 06:19:32

标签: java jdbc playframework nonblocking

我试图在概念上理解为什么在Play Framework 2.0中,将WS.url().get()称为Web服务调用被视为最佳实践,但是如果您将任何其他阻塞调用(例如JDBC调用)包装起来一个promise,建议你在默认执行上下文以外的执行上下文中执行它?

据我所知,默认情况下,Play Framework的线程池配置为每个核心有一个线程,每个控制器都希望运行完全无阻塞的代码。因此,如果您在控制器中进行阻塞调用(例如,对Web服务),那么您需要确保此调用不会阻止可用于控制器的线程。

否则,没有线程可以执行控制器,因为它们都处于阻塞状态等待。

但令我困惑的是以下几点:

  • 首先,控制器代码本身执行什么线程池?这是默认的执行上下文吗?
  • 其次,一方面我理解WS.url().get()也在默认执行上下文中执行,但另一方面,Play Framework Documentation on Thread Pool Configuration表示"请注意,您可以被诱惑...将您的阻止代码包装在期货中。这不会阻止它,它只是意味着阻塞将在不同的线程中发生。"

上述意思不是WS.url().get()是"只是发生在不同的线程"在相同的默认执行上下文中?在不同的执行上下文中执行JDBC调用有什么不同?

1 个答案:

答案 0 :(得分:5)

1)播放控制器功能在Play的默认线程池中执行,如链接文档中所述:

  

播放默认线程池 - 这是默认线程池,其中执行Play Framework中的所有应用程序代码。它是Akka调度程序,可以通过配置Akka进行配置,如下所述。默认情况下,每个处理器有一个线程。

因此,您需要非常小心阻塞控制器函数,因为这会阻塞默认线程池中的线程。

2)播放网络服务是一种非阻止API,因此不会阻止它ExecutionContext。因此,可以在控制器函数中进行多次WS调用,而不会阻塞默认线程池。 WS调用和JDBC调用之间的主要区别在于WS调用在等待来自远程服务器的响应时不会阻塞线程,这些调用是异步调用的。 JDBC调用(像大多数java IO一样)会在等待响应时阻塞它的线程。

在另一个ExecutionContext内执行JDBC调用将释放默认ExecutionContext以执行其他工作,从而允许您的服务器处理更多请求。您可以让Akka为您处理上下文切换的艰苦工作。虽然JDBC调用仍然阻塞了一个线程,但它们至少不会阻塞处理请求的线程。