背景
我正在通过 r2d2 使用柴油开发一个 actix-web 应用程序,并且不确定如何最好地进行异步查询。我找到了三个看起来合理的选项,但不确定哪个是最好的。
潜在的解决方案
同步演员
对于一个我可以使用actix 示例,但它非常复杂,并且需要大量的样板来构建。我希望有一个更合理的解决方案。
Actix_web::web::block
作为另一种选择,我可以使用actix_web::web::block
将我的查询函数包装到未来,但我不确定这对性能的影响。
然后查询是否在同一个 Tokio 系统中运行?根据我在源代码中可以找到的内容,它在底层 actix-web threadpool 中创建了一个线程。那是问题吗?
如果我没看错代码,r2d2 在获取连接时会阻塞它的线程,这会阻塞部分核心 actix-web 池。与数据库查询相同。如果我执行的查询多于该池中的线程数,这会阻止所有 actix-web 吗?如果是这样,问题就大了。
期货-cpupool
最后,可能有一些不必要的开销的安全赌注是futures-cpupool。主要问题是这意味着在我的项目中添加另一个板条箱,尽管我不喜欢在我的应用程序中不必要地浮动多个 cpu 池的想法。
由于 r2d2 和柴油都会阻塞,因此这里有很多棘手的事情。
最重要的是,不要与不使用同一个 r2d2 池的任何东西共享这个 cpupool(因为创建的所有线程可能只是阻塞等待 r2d2 连接,当工作存在时锁定整个池)。
其次(更明显一点),因此您不应该比池中的线程拥有更多的 r2d2 连接,反之亦然,因为较大的连接会浪费资源(未使用的连接/线程不断阻塞)(可能多一个线程,可能更快由 OS 调度程序而不是 cpupool 调度程序进行连接切换)。
最后,请注意您使用的是什么数据库以及那里的性能。在写入繁重的 sqlite 应用程序中运行单个连接 r2d2 和池中的单个线程可能是最好的(尽管我会推荐一个合适的数据库)。
旧答案
可能有效的旧解决方案
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
本质上,推荐 Futures-cpupool。
在 future-rs 中封装阻塞 I/O 的最佳方法是什么?
一般情况下推荐 Futures-cpupool。
不起作用的旧解决方案
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
对旧的 actix-web 版本的一个非常好的修复。从我可以找到的请求中不再有 cpu 池。