Akka:如何制作非阻塞JDBC请求

时间:2015-07-27 01:13:20

标签: java jdbc akka

我是Akka( Java lib )的新手,我试图了解Akka是否可用于向JDBC发出非阻塞请求,如果是,那么它会是什么样子。我相信大多数JDBC驱动程序打开套接字连接并阻塞创建它的线程,直到收到特定的JDBC响应,因此可能没有太多Akka可以帮助到这里,但我想知道是否有一种方法(可能通过Futures或Agent?),Akka可以帮助提高性能,并允许actor系统继续处理数据,同时正在进行现有的JDBC调用并等待响应。

我发现this article有点模糊/含糊,但听起来未来可能是关键所在。然而,该文章并没有真正展示任何有意义的(真实世界)代码示例,因此我仍然处于亏损状态。因此,假设我们有一个存储过程sp_make_expensive_calculation,通常需要10 - 30秒才能返回响应,而且通常通过JDBC调用,如下所示:

String makeExpensiveCalculationSql = "{call sp_make_expensive_calculation(?)}";
callableStatement = dbConnection.prepareCall(makeExpensiveCalculationSql);
callableStatement.setInt(1, 10);

// Could take up to 30 seconds to complete.
callableStatement.executeUpdate();

int answer = callableStatement.getString(2);

Akka可以做任何事情来帮助这些,以便演员系统可以继续处理数据(甚至进行其他sp_make_expensive_calculation调用),同时我们等待第一次调用返回吗?

2 个答案:

答案 0 :(得分:7)

一般模式是使用单独的execution contexts:一个用于通过JDBC进行同步数据库访问,一个用于反应式处理。另请参阅Akka futures documentation

当您创建一个actor系统时,它会创建自己的执行上下文 - 这是您用于与actor进行正常反应处理的上下文。您需要为JDBC调用创建第二个执行上下文。然后,您将把此执行上下文传递给将来的工厂,如here in the Akka documentation所示。

为了在未来完成时收到通知,您可以(可选)使用管道构造(也显示在上一个链接中,但在前面的文档部分中)。管道构造的效果是获取future的返回值,其类型是future的泛型类型参数(例如,查询的结果),并将其发布到指定的actor的邮箱。

未来执行的代码不得修改甚至读取发起者(或任何参与者)拥有的任何可变数据。您需要标记未来的结果,以便当它到达actor的邮箱时,actor可以将它与初始JDBC请求相关联。最后,你的演员最终会收到结果,你可以继续处理它(根据Akka的最多一次交付保证)。

请注意, 没有使用两个执行上下文 - 一个也可以工作,但是数据库请求会占用执行上下文中所有可用线程的危险。

答案 1 :(得分:2)

你是正确的,JDBC连接将阻塞,直到请求通过,但如果你将它包装在异步处理器中,你可以允许它完成并让主线程继续。

让请求者访问JDBC请求结果的一种方法是提供在异步数据库进程完成时调用的回调。