背景
我正在使用diesel通过r2d2开发actix-web应用程序,但不确定如何最好地进行异步查询。我找到了三个看起来合理的选项,但不确定哪个是最好的。
潜在解决方案
同步Actor
首先,我可以使用actix示例,但这相当复杂,并且需要大量的样板文件来构建。我希望存在更合理的解决方案。
Actix_web::web::block
作为另一种选择,我可以使用actix_web::web::block
将我的查询函数包装成一个future,但我不确定性能影响如何。
那么查询是否在同一个Tokio系统中运行?从源代码中可以找到它在底层的actix-web线程池中创建一个线程。这是一个问题吗?
如果我正确理解代码,r2d2在获取连接时会阻塞其线程,这将阻塞actix-web池的一部分。数据库查询也是如此。如果我执行的查询数超过该池中的线程数,则会阻塞整个actix-web。如果是这样,那就是一个大问题。
Futures-cpupool
最终,一个安全但可能有些不必要开销的选择是futures-cpupool。主要问题是这意味着在我的项目中添加另一个crate,尽管我不喜欢应用程序中不必要地出现多个CPU池的想法。
由于r2d2和diesel都会阻塞,因此这里有许多棘手的问题。
最重要的是,不要与未使用相同r2d2池的任何内容共享此cpupool(因为所有创建的线程可能只是等待r2d2连接而阻塞,当存在工作时锁定整个池)。
其次(更明显一些),因此您不应该拥有比池中的线程更多的r2d2连接,反之亦然,因为更大的那个将浪费资源(未使用的连接/常常被阻塞的线程)(也许还需要一个线程,以便操作系统调度程序可以更快地进行连接交接,而不是cpupool调度程序)。
最后,要注意您正在使用的数据库及其性能。在写入密集的SQLite应用程序中,运行单个连接r2d2和池中的单个线程可能是最佳选择(尽管我建议使用适当的数据库进行此操作)。
旧答案
可能有效的旧解决方案
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
实质上,推荐使用Futures-cpupool。
一般情况下,推荐使用Futures-cpupool。
不起作用的旧解决方案
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
一个非常好的旧版本actix-web的修复。从我能找到的资料中,请求不再包含CPU池。
futures-cpupool
是在Diesel缺乏async
支持时推荐的解决方法。 - Jmb