Должен ли дизель запускаться с использованием актера синхронизации, actix_web :: web :: block или futures-cpupool?

10

Фон

Я работаю над веб-приложением 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.
JMB
Это скорее общее решение. Я надеюсь на то, что будет использовать систему actix. Тем не менее, я сейчас покопаюсь в futures-cpupool, чтобы искать проблемы.
логина
Добро пожаловать в переполнение стека! Похоже, что на ваш вопрос могут быть даны ответы Каков наилучший подход для инкапсуляции блокирующих операций ввода-вывода в будущем? , Если нет, пожалуйста, отредактируйте свой вопрос, чтобы объяснить различия. В противном случае мы можем пометить этот вопрос как уже отвеченный.
Shepmaster
Так как cpupool также взаимодействует с пулом блокирующих соединений в r2d2, я не уверен, как лучше решить эту проблему. Я сам сейчас в этом разбираюсь и скоро обновлюсь.
логина

Ответы:

3

Я собираюсь с фьючерсами-cpupool. Это лучшее решение из-за блокирующего характера моих взаимодействий.

Использование actix_web :: web :: block достаточно прилично, но в actix будет использоваться общий пул потоков (и из-за блокирующих вызовов, которые я использую, это может блокировать весь пул потоков и мешать другим задачам, переданным actix_web).

Лучше использовать futures-cpupool для создания отдельного пула потоков для каждой базы данных только для взаимодействия с базой данных. Таким образом, вы группируете все задачи, которые должны ждать друг друга (когда задач больше, чем подключений), в один пул, не позволяя им блокировать любые другие задачи, для которых не требуется подключение, и потенциально ограничивая количество потоков до количество соединений (так что задача будет запланирована только тогда, когда она не будет заблокирована).

В случае, когда вы хотите использовать только одно соединение с базой данных (или очень мало), субъект синхронизации является довольно хорошим вариантом. Он будет действовать как futures-cpupool с одним потоком, гарантируя, что все задачи будут выполняться по одному, за исключением того, что он будет использовать один из базовых потоков actix-web, а не отдельный (поэтому подходит только для очень немногих соединений) , Я нахожу шаблон слишком большим, чтобы того стоить.

Логина
источник
6
прочитав мои выводы выше - пожалуйста , информацию пут , имеющие отношение к ответу в ответ , а не вопрос.
Шепмастер