Фон
Я работаю над веб-приложением actix, использующим дизель через r2d2, и не знаю, как лучше всего выполнять асинхронные запросы. Я нашел три варианта, которые кажутся разумными, но я не уверен, какой из них лучше.
Потенциальные решения
Синхронный актер
В качестве примера я мог бы использовать пример actix , но он довольно сложный и требует значительного количества стандартного образца для сборки. Я надеюсь, что существует более разумное решение.
Actix_web::web::block
В качестве другого варианта я мог бы использовать actix_web::web::block
для переноса своих запросов в будущее, но я не уверен в последствиях для производительности.
Запускается ли тогда запрос в той же системе Tokio? Из того, что я мог найти в источнике, он создает поток в базовом пуле потоков actix-web . Это проблема?
Если я правильно прочитал код, r2d2 блокирует свой поток при установлении соединения, что блокирует часть основного пула actix-web. То же самое с запросами к базе данных. Это тогда заблокировало бы все actix-web, если я делаю больше запросов, чем у меня потоков в этом пуле? Если это так, большая проблема.
Фьючерс-cpupool
Наконец, безопасная ставка, которая может иметь некоторые ненужные накладные расходы, - это futures-cpupool . Основная проблема заключается в том, что это означает добавление еще одного ящика в мой проект, хотя мне не нравится идея, что в моем приложении будет ненужно использовать несколько процессорных пулов.
Поскольку и r2d2, и дизель блокируют, здесь есть удивительное количество хитрых вещей.
Самое главное, не делитесь этим cpupool ни с кем, не использующим один и тот же пул r2d2 (поскольку все созданные потоки могут просто блокировать ожидание соединения r2d2, блокируя весь пул, когда работа существует).
Во-вторых (немного более очевидно), таким образом, вы не должны иметь больше соединений r2d2, чем потоков в пуле, и наоборот, так как больший из них будет тратить ресурсы (неиспользуемые соединения / потоки постоянно блокируются) (возможно, еще один поток, возможно, быстрее). передача соединения планировщиком ОС, а не планировщиком cpupool).
Наконец, обратите внимание, какую базу данных вы используете, и какую производительность вы используете. Выполнение одного соединения r2d2 и одного потока в пуле может быть лучше всего для приложения с тяжелой записью sqlite (хотя я бы порекомендовал для этого подходящую базу данных).
Старые ответы
Старые решения, которые могут работать
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. Из того, что я могу найти запросы, больше нет процессорного пула в них.
источник
futures-cpupool
это рекомендуемое решение проблемы отсутствияasync
поддержки в Diesel.Ответы:
Я собираюсь с фьючерсами-cpupool. Это лучшее решение из-за блокирующего характера моих взаимодействий.
Использование actix_web :: web :: block достаточно прилично, но в actix будет использоваться общий пул потоков (и из-за блокирующих вызовов, которые я использую, это может блокировать весь пул потоков и мешать другим задачам, переданным actix_web).
Лучше использовать futures-cpupool для создания отдельного пула потоков для каждой базы данных только для взаимодействия с базой данных. Таким образом, вы группируете все задачи, которые должны ждать друг друга (когда задач больше, чем подключений), в один пул, не позволяя им блокировать любые другие задачи, для которых не требуется подключение, и потенциально ограничивая количество потоков до количество соединений (так что задача будет запланирована только тогда, когда она не будет заблокирована).
В случае, когда вы хотите использовать только одно соединение с базой данных (или очень мало), субъект синхронизации является довольно хорошим вариантом. Он будет действовать как futures-cpupool с одним потоком, гарантируя, что все задачи будут выполняться по одному, за исключением того, что он будет использовать один из базовых потоков actix-web, а не отдельный (поэтому подходит только для очень немногих соединений) , Я нахожу шаблон слишком большим, чтобы того стоить.
источник