柴油机应该使用同步参与者 actix_web::web::block 还是 futures-cpupool 运行?

Posted

技术标签:

【中文标题】柴油机应该使用同步参与者 actix_web::web::block 还是 futures-cpupool 运行?【英文标题】:Should diesel be run using a sync actor, actix_web::web::block or futures-cpupool? 【发布时间】:2020-03-05 01:39:30 【问题描述】:

背景

我正在开发一个通过 r2d2 使用柴油的 actix-web 应用程序,但我不确定如何最好地进行异步查询。我找到了三个看起来合理的选项,但不确定哪个最好。

可能的解决方案

同步演员

我可以使用the actix example,但它非常复杂,需要大量的样板来构建。希望有更合理的解决方案。

Actix_web::web::block

作为另一种选择,我可以使用 actix_web::web::block 将我的查询函数包装到未来,但我不确定这对性能的影响。

查询是否在同一个 Tokio 系统中运行?根据我在源代码中可以找到的内容,it creates a thread in the underlying actix-web threadpool。有问题吗?

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

期货-cpupool

最后,可能会有一些不必要的开销的安全赌注是futures-cpupool。主要问题是这意味着向我的项目添加另一个 crate,尽管我不喜欢在我的应用程序中不必要地浮动多个 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。

What is the best approach to encapsulate blocking I/O in future-rs?

推荐 Futures-cpupool 用于一般情况。

不起作用的旧解决方案

https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/

对旧的 actix-web 版本进行了非常好的修复。据我所知,请求中不再有 cpu 池。

【问题讨论】:

从 this issue 中的 cmets 看来,futures-cpupool 是推荐的解决方法,因为 Diesel 缺乏对 async 的支持。 这更像是一个通用的解决方案。我希望有一些可以利用 actix 系统的东西。尽管如此,我现在将深入研究 futures-cpupool 以寻找问题。 欢迎来到 Stack Overflow! What is the best approach to encapsulate blocking I/O in future-rs? 的答案似乎可以回答您的问题。如果没有,请edit您的问题来解释差异。否则,我们可以将此问题标记为已回答。 由于 cpupool 还与 r2d2 中的阻塞连接池交互,我不确定如何最好地解决这个问题。我现在正在自己研究它,很快就会更新。 【参考方案1】:

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

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

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

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

【讨论】:

阅读我上面的发现 — 请将与答案相关的信息放在答案中,而不是问题中。 你会推荐多大的池?

以上是关于柴油机应该使用同步参与者 actix_web::web::block 还是 futures-cpupool 运行?的主要内容,如果未能解决你的问题,请参考以下文章

柴油机排气后处理系统电子控制单元

柴油机编译挂在 Lightsail 上

75kW柴油发电机组的可靠性设计

技术75kW柴油发电机组的可靠性设计

在柴油塔中使用新型

Rust,Windows 10:柴油机不工作,柴油机设置不提供输出