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

sme*_*eeb 9 java jdbc akka

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

我发现这篇文章有点模糊/含糊不清,但听起来未来可能是关键所在.然而,该文章并没有真正展示任何有意义的(真实世界)代码示例,因此我仍然处于亏损状态.因此,假设我们有一个存储过程,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);
Run Code Online (Sandbox Code Playgroud)

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

kil*_*ilo 8

一般模式是使用单独的执行上下文:一个用于通过JDBC进行同步数据库访问,一个用于反应式处理.另请参阅Akka期货文档.

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

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

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

请注意,您不具备使用两个执行上下文-一个也将工作,但仍然会有消耗在执行上下文中的所有可用线程的数据库请求的危险.