Contexte
Je travaille sur une application actix-web utilisant le diesel via r2d2 et je ne suis pas sûr de la meilleure façon de faire des requêtes asynchrones. J'ai trouvé trois options qui semblent raisonnables, mais je ne sais pas laquelle est la meilleure.
Solutions potentielles
Acteur de synchronisation
D'une part, je pourrais utiliser l'exemple d'actix , mais il est assez compliqué et nécessite beaucoup de passe-partout pour être construit. J'espère qu'il existe une solution plus raisonnable.
Actix_web::web::block
Comme autre option, je pourrais utiliser le actix_web::web::block
pour encapsuler mes fonctions de requête dans un avenir, mais je ne suis pas sûr des implications en termes de performances.
La requête s'exécute-t-elle alors dans le même système Tokio? D'après ce que j'ai pu trouver dans la source, il crée un thread dans le pool de threads actix-web sous-jacent . Est-ce un problème?
Si je lis le code correctement, r2d2 bloque son thread lors de l'acquisition d'une connexion, ce qui bloquerait une partie du pool d'actix-web principal. Même chose avec les requêtes de base de données. Cela bloquerait alors tout l'actix-web si je fais plus de requêtes que j'ai de threads dans ce pool? Si oui, gros problème.
Futures-cpupool
Enfin, le pari sûr qui peut avoir des frais généraux inutiles est futures-cpupool . Le problème principal est que cela signifie ajouter une autre caisse à mon projet, bien que je n'aime pas l'idée de plusieurs cpu-pools flottant inutilement dans mon application.
Étant donné que le r2d2 et le diesel se bloqueront, il y a une quantité surprenante de choses délicates ici.
Plus important encore, ne partagez pas ce cpupool avec quoi que ce soit n'utilisant pas le même pool r2d2 (car tous les threads créés peuvent simplement bloquer l'attente d'une connexion r2d2, verrouillant tout le pool lorsque le travail existe).
Deuxièmement (un peu plus évidemment), vous ne devriez donc pas avoir plus de connexions r2d2 que de threads dans le pool et vice-versa car le plus gros gaspillerait des ressources (connexions inutilisées / threads constamment bloqués) (peut-être un thread de plus, pour peut-être plus rapide transfert de connexion par le planificateur du système d'exploitation plutôt que par le planificateur cpupool).
Enfin, pensez à la base de données que vous utilisez et aux performances que vous y avez. L'exécution d'une seule connexion r2d2 et d'un seul thread dans le pool peut être préférable dans une application sqlite lourde en écriture (bien que je recommanderais une base de données appropriée pour cela).
Anciennes réponses
Anciennes solutions qui peuvent fonctionner
https://www.reddit.com/r/rust/comments/axy0hp/patterns_to_scale_actixweb_and_diesel/
Essentiellement, recommande Futures-cpupool.
Quelle est la meilleure approche pour encapsuler les E / S bloquantes dans les futurs rs?
Recommande Futures-cpupool pour les cas généraux.
De vieilles solutions qui ne fonctionnent pas
https://www.reddit.com/r/rust/comments/9fe1ye/noob_here_can_we_talk_about_async_and_databases/
Une très bonne solution pour une ancienne version d'actix-web. D'après ce que je peux trouver, les demandes n'ont plus de pool de processeurs.
futures-cpupool
c'est la solution de contournement recommandée pour le manque deasync
support dans Diesel.