我可能误解了 Play Framework (2.x) 的一些基本内容,但是关于访问普通 SQL 数据库的文档和这样做的项目示例似乎都没有异步执行此操作。
没有Promise<Result>
,没有 Akka 的东西等。
如果您使用普通的 MySQL JDBC 驱动程序进行数据库查询,您是否不会阻塞主服务器线程?我错过了什么?
我可能误解了 Play Framework (2.x) 的一些基本内容,但是关于访问普通 SQL 数据库的文档和这样做的项目示例似乎都没有异步执行此操作。
没有Promise<Result>
,没有 Akka 的东西等。
如果您使用普通的 MySQL JDBC 驱动程序进行数据库查询,您是否不会阻塞主服务器线程?我错过了什么?
是的,db 驱动程序阻塞了等待数据库结果的线程。
即使您像 ico_ekito 建议的那样将 JDBC 调用包装在 Akka 未来中,它仍然会在整个数据库请求期间阻塞一个服务器线程。这样做可能只会在不同的线程上执行调用(取决于 Akka 决定如何执行它),但它仍然会阻塞该线程。
解决此问题的唯一正确方法是使用非阻塞数据库驱动程序。
顺便说一句,您可以很容易地发现阻塞的数据库驱动程序。如果它的界面看起来像这样:
ResultSet results = connection.execute(query);
它肯定是阻塞的。您可以通过返回 Futures、Promises(具有写入端的 Futures)或接受回调的方法来识别非阻塞 API。
另请注意,没有“主”服务器线程(如浏览器/桌面应用程序中的 UI 线程)。只有几个线程处理请求。
如需更深入的讨论,请查看此处。
AFAIK,如果您正在查看“计算机数据库”示例,那么您是完全正确的,它阻塞了主线程,因为操作不是异步执行的。
这是样本的摘录:
public static Result list(int page, String sortBy, String order, String filter) {
return ok(
list.render(
Computer.page(page, 10, sortBy, order, filter),
sortBy, order, filter
)
);
}
在这里,Computer.page()
正在执行一些 JDBC 阻塞调用。
如果您想异步执行此操作,则应将数据库调用包含在async(F.Promise<Result>)
调用中。像这样的东西:
public static Result list(int page, String sortBy, String order, String filter) {
return async(
Akka.future(
new Callable<Result>() {
public Result call() {
return ok(
list.render(
Computer.page(page, 10, sortBy, order, filter),
sortBy, order, filter
)
);
}
}
)
);
}