首页 > 解决方案 > Scala Future 中包装的 JDBC 调用

问题描述

我正在编写一个 Akka HTTP Web API,它使用 OJDBC 连接到一个 Oracle 数据库实例。

据我所知,没有用于连接数据库的异步 JDBC API,也没有回调实现,因此,必须阻塞进程线程才能完成调用。

我的问题是:拥有 Akka HTTP 自然允许使用 Scala Future 处理请求,将数据库调用简单地包装到 Scala Future 中是否是个好主意?等待数据库响应时底层线程是否空闲?

标签: scalajdbcconcurrencyfuture

解决方案


等待数据库响应时底层线程是否空闲? 是的,线程被阻塞直到 JDBC 调用完成。这不是一件好事,但在adba准备好之前,可能没有更好的选择。

使用Future阻塞 IO(如JDBC调用)是一种常见的模式。不过有一些事情需要考虑。github上有一篇关于该主题的精彩文章。

总结文章中描述的事情的几点:

  • 将阻塞调用包装在blocking块内,如下所示:

    def fetchUser(id: Long): Future[User]  = Future {
       blocking { //mark this operation as blocking
          ...
          preparedStatement.execute()
          ...
       }
    } 
    
  • 你不应该使用scala.concurrent.ExecutionContext.Implicits.global做任何阻塞的期货,因为你可能会饿死线程池。您应该为阻塞操作创建一个单独的线程池:

    object BlockingIOExecutionContext {
        implicit val ec: ExecutionContextExecutor = ExecutionContext.fromExecutor(
           Executors.newCachedThreadPool()
        ) // create seperate thread pool for our blocking operations
    }
    

对你来说最好的选择就是使用某种成熟的 Scala 框架,为你做这些事情,比如slickdoobie


推荐阅读