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

Фон

Я работаю над веб-приложением actix, использующим дизель через r2d2, и не знаю, как лучше всего выполнять асинхронные запросы. Я нашел три варианта, которые кажутся разумными, но я не уверен, какой из них лучше.

Потенциальные решения

Синхронный актер

Для одного я мог бы использовать actixпример , но он довольно сложный и требует изрядного количества шаблонов для сборки. Я надеюсь, что существует более разумное решение.

Actix_web::web::block

В качестве другого варианта я мог бы использовать actix_web::web::block, чтобы обернуть свои функции запросов в будущее, ноЯ не уверен, что это повлияет на производительность.

Запускается ли тогда запрос в той же системе Tokio? Из того, что я мог найти в источнике, создает поток в базовом пуле потоков actix-web . Это проблема?

Если я правильно прочитал код, r2d2 блокирует свой поток при получении соединения, что блокирует часть основного пула actix-web. То же самое с запросами к базе данных. Это тогда заблокировало бы все actix-web, если я делаю больше запросов, чем у меня потоков в этом пуле? Если это так, большая проблема.

Futures-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. Из того, что я могу найти, запросы больше не содержат пул процессоров.

1 Ответ

0 голосов
/ 08 ноября 2019

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

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

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

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

...