Background

我正在使用diesel通过r2d2开发一个actix web应用程序,不确定如何最好地进行异步查询.我找到了三个似乎合理的 Select ,但不确定哪一个是最好的.

Potential Solutions

同步演员

例如,我可以使用the actix example,但它相当复杂,需要大量的样板来构建.我希望有一个更合理的解决方案.

Actix_web::web::block

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

那么这个查询是在同一个Tokio系统中运行的吗?根据我在资料中找到的it creates a thread in the underlying actix-web threadpool.这有问题吗?

如果我读对了代码,r2d2在获取连接时会阻塞其线程,这会阻塞核心actix web池的一部分.数据库查询也是如此.如果我做的查询比池中的线程多,这会阻止所有actix web吗?如果是的话,那就是一个大问题.

期货cpupool

最后,可能有一些不必要的开销的安全赌注是futures-cpupool.主要的问题是,这意味着在我的项目中添加另一个 crate ,尽管我不喜欢在我的应用程序中不必要地浮动多个cpu池的 idea .

因为r2d2和柴油机都会堵塞,所以这里有很多棘手的事情.

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

其次(更明显一点),因此池中的r2d2连接不应该比线程多,反之亦然,因为较大的r2d2连接会浪费资源(未使用的连接/线程不断被阻塞)(可能多一个线程,以便OS调度器而不是cpupool调度器更快地进行连接切换).

最后,请注意您正在使用的数据库及其性能.在编写量大的sqlite应用程序中,运行单个连接r2d2和池中的单个线程可能是最好的(尽管我建议为此类应用程序使用合适的数据库).

Old answers

可能有效的旧解决方案

https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/

本质上,cpupool是.

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

建议在一般情况下使用cpupool.

不起作用的旧解决方案

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

对于旧的actix web版本来说,这是一个非常好的修复.据我所知,请求中不再有cpu池.

推荐答案

我要和cpupool一起go .这是最好的解决方案,因为我的交互具有阻塞性.

使用actix_web::web::block已经足够好了,但会在actix中使用一个共享线程池(由于我使用的阻塞调用,这可能会阻塞整个线程池,并干扰分配给actix_web的其他任务).

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

如果只想使用一个数据库连接(或很少),那么sync actor是一个不错的 Select .它将像一个带有一个线程的future cpupool,确保所有任务一次运行一个,但它将使用actix web的一个底层线程,而不是一个单独的线程(因此,只适用于极少数连接).不过,我觉得这个样板太大了,不值得这么做.

Rust相关问答推荐

移植带有可变borrow 的C代码-卸载期间错误(nappgui示例)

在Rust中创建可变片段的可变片段的最有效方法是什么?

Rust kill std::processs::child

在函数内定义impl和在函数外定义impl的区别

铁 rust 中的泛型:不能将`<;T作为添加>;::Output`除以`{Float}`

当对VEC;U8>;使用serde_json时,Base64编码是保护空间的好方法吗?

如何实现Serde::Ser::Error的调试

为什么`AlternateScreen`在读取输入键时需要按Enter键?

在Rust 中移动原始指针的靶子安全吗

在 Rust 中用问号传播错误时对类型转换的困惑?

如何将一个矩阵的列分配给另一个矩阵,纳尔代数?

根据掩码将 simd 通道设置为 0 的惯用方法?

需要一个有序向量来进行 struct 初始化

Rust 中指向自身的引用如何工作?

如何展平以下嵌套的 if let 和 if 语句?

LinkedList::drain_filter::drop 中 DropGuard 的作用是什么?

如何在 Rust 中返回通用 struct

Rustlings 切片原语

Cargo:如何将整个目录或文件包含在功能标志中?

为什么我可以从读取的可变自引用中移出?