是否应该使用同步角色,actix_web :: web :: block或futures-cpupool运行柴油?

log*_*ina 6 rust rust-diesel actix-web

背景

我正在通过r2d2使用柴油的actix-web应用程序上工作,并且不确定如何最好地进行异步查询。我发现了三个看似合理的选择,但不确定哪个是最好的。

潜在解决方案

同步演员

对于我来说,我可以使用actix示例,但是它非常复杂,需要大量样板来构建。我希望有一个更合理的解决方案。

Actix_web::web::block

作为另一种选择,我可以使用将actix_web::web::block查询功能包装到将来,但是我不确定这样做的性能含义。

然后,该查询是否在同一Tokio系统中运行?从我在源代码中可以找到的地方,它在基础的actix-web线程池中创建了一个线程。那是问题吗?

如果我没看错代码,则r2d2在获取连接时会阻塞其线程,这会阻塞部分核心actix-web池。与数据库查询相同。如果我执行的查询多于该池中的线程数,那么这将阻止所有actix-web?如果是这样,那就大问题了。

期货

最后,可能会有一些不必要开销的安全选择是futures-cpupool。主要问题是,这意味着要向我的项目中添加另一个板条箱,尽管我不喜欢不必要地在应用程序中浮动多个cpu池的想法。

由于r2d2和柴油都会阻塞,因此这里有令人惊讶的棘手事情。

最重要的是,不要与不使用同一r2d2池的任何事物共享此cpupool(因为创建的所有线程可能只是阻塞等待r2d2连接,在工作存在时锁定整个池)。

其次(更明显一点),因此您不应该拥有比池中线程更多的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池。

log*_*ina 4

我将使用 futures-cpupool。由于我的交互具有阻塞性质,这是最好的解决方案。

使用 actix_web::web::block 就足够了,但会在 actix 中使用共享线程池(并且由于我使用的阻塞调用可能会阻塞整个线程池并干扰交给 actix_web 的其他任务)。

最好使用 futures-cpupool 为每个数据库创建一个单独的线程池,仅用于数据库交互。通过这种方式,您可以将所有需要相互等待的任务(当任务多于连接数时)分组到一个池中,防止它们阻塞任何其他不需要连接的任务,并可能将线程数限制为连接数(这样任务只有在不会被阻塞时才会被调度)。

如果您只想使用一个(或很少)数据库连接,同步参与者是一个非常好的选择。它将像一个具有一个线程的 futures-cpupool 一样,确保所有任务一次运行一个,只不过它将使用 actix-web 的底层线程之一而不是单独的线程(因此,仅适用于很少的连接) 。不过,我发现样板太大了,不值得。

  • *阅读我上面的发现* - 请将与*答案*相关的信息放在**答案**中,而不是问题中。 (7认同)