我试图从概念上理解为什么在 Play Framework 2.0 中,调用被认为是最佳实践WS.url().get()
对于 Web 服务调用,但是如果您将任何其他阻塞调用(例如 JDBC 调用)包装在 Promise 中,是否建议您在默认执行上下文以外的执行上下文中执行此操作?
据我所知,默认情况下,Play Framework 的线程池配置为每个核心有一个线程,并且每个控制器都希望运行完全非阻塞的代码。因此,如果您在控制器中进行阻塞调用(例如,对 Web 服务),那么您需要确保此调用不会占用控制器可用的线程。
否则,将没有线程可以执行控制器,因为它们都在阻塞状态下等待。
但令我困惑的是以下几点:
- 首先,控制器代码本身在哪个线程池中执行?这是默认的执行上下文吗?
- 其次,一方面我理解
WS.url().get()
也在默认执行上下文中执行,但另一方面,Play框架文档关于线程池配置 https://playframework.com/documentation/2.3.x/ThreadPools指出“请注意,您可能会想……将阻塞代码包装在 Futures 中。这并不意味着它是非阻塞的,它只是意味着阻塞将发生在不同的线程中。”
上面的意思是不是WS.url().get()
是在同一个默认执行上下文中“只是发生在不同的线程中”吗?在不同的执行上下文中执行 JDBC 调用有什么不同?
1) Play 控制器函数在 Play 的默认线程池中执行,如链接文档中所述:
Play 默认线程池 - 这是执行 Play Framework 中所有应用程序代码的默认线程池。它是一个 Akka 调度程序,可以通过配置 Akka 进行配置,如下所述。默认情况下,每个处理器有一个线程。
因此,您需要非常小心地处理控制器函数内的阻塞,因为这会阻塞默认线程池中的线程。
2) Play Web 服务是非阻塞 API,因此does not阻止它的ExecutionContext
。因此,你can在控制器函数中进行多次 WS 调用,而不会阻塞默认线程池。 WS 调用和 JDBC 调用之间的主要区别在于,WS 调用在等待远程服务器响应时不会阻塞线程,调用是异步进行的。 JDBC 调用(像大多数 java IO 一样)将在等待响应时阻塞其线程。
在不同的环境中执行 JDBC 调用ExecutionContext
将释放默认值ExecutionContext
做其他工作,从而允许您的服务器处理更多请求。你可以让 Akka 为你处理上下文切换的繁重工作。虽然 JDBC 调用仍然阻塞线程,但它们至少不会阻塞处理请求的线程。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)