代码之家  ›  专栏  ›  技术社区  ›  Josh Padnick

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

  •  3
  • Josh Padnick  · 技术社区  · 10 年前

    我试图从概念上理解为什么在Play Framework 2.0中,调用 WS.url().get() 对于web服务调用,但是如果您在promise中包装任何其他阻塞调用(如JDBC调用),建议您在默认执行上下文以外的执行上下文中执行?

    我知道,默认情况下,PlayFramework的线程池被配置为每个内核有一个线程,每个控制器都希望运行完全无阻塞的代码。因此,如果在控制器中进行阻塞调用(例如,对web服务),则需要确保此调用不会占用控制器可用的线程。

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

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

    • 首先,控制器代码本身在哪个线程池中执行?这是默认的执行上下文吗?
    • 第二,一方面我明白 WS-url().get() 也在默认执行上下文中执行,但另一方面 Play Framework Documentation on Thread Pool Configuration 声明: “请注意,您可能会尝试……在Futures中包装您的阻塞代码。这并不意味着它是非阻塞的,它只是意味着阻塞将发生在不同的线程中。”

    以上这些不意味着 WS-url().get() “只是在不同的线程中发生”在相同的默认执行上下文中吗?在不同的执行上下文中执行JDBC调用有什么不同?

    1 回复  |  直到 10 年前
        1
  •  5
  •   Michael Zajac    10 年前

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

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

    因此,您需要非常小心地在控制器函数内进行阻塞,因为这将阻塞默认线程池中的线程。

    2) Play web服务是一个非阻塞API,因此它 没有 阻止它 ExecutionContext 。因此,您 可以 在控制器函数中进行多个WS调用,而不阻塞默认线程池。WS调用和JDBC调用之间的主要区别在于,在等待远程服务器的响应时,WS调用不会阻塞线程,调用是异步进行的。JDBC调用(与大多数java IO一样)在等待响应时会阻塞其线程。

    在不同的 执行上下文 将释放默认值 执行上下文 以执行其他工作,从而允许服务器处理更多请求。你可以让Akka为你处理上下文切换的辛苦工作。虽然JDBC调用仍在阻塞线程,但它们至少没有阻塞处理请求的线程。