🚧 Attention, peinture fraîche !
Cette page a été traduite par une seule personne et n'a pas été relue et vérifiée par quelqu'un d'autre ! Les informations peuvent par exemple être erronées, être formulées maladroitement, ou contenir d'autres types de fautes.
L'écosystème asynchrone
Actuellement, Rust ne fournit que l'essentiel pour écrire du code asynchrone. En particulier, les exécuteurs, les tâches, les réacteurs, les combinateurs, et les futures et les traits de bas-niveau d'entrée/sortie ne sont pas encore fournis par la bibliothèque standard. Mais en attendant, les écosystèmes asynchrones fournis par la communauté répondent à ce besoin.
L'équipe en charge des fondations de l'asynchrone est intéressée par le développement dans le livre sur l'asynchrone pour couvrir plusieurs environnements d'exécution. Si vous êtes intéressé pour contribuer à ce projet, veuillez vous rendre sur Zulip.
Les environnements d'exécution asynchrone
Les environnements d'exécution asynchrones sont des bibliothèques utilisées pour exécuter des applications asynchrones. Les environnements d'exécution embarquent généralement ensemble un réacteur avec un ou plusieurs exécuteurs. Les réacteurs fournissent des mécanismes d'abonnement pour les évènements externes, comme les entrées/sorties asynchrones, la communication entre les processus, et les temporisations. Dans un environnement d'exécution asynchrone, les abonnés sont typiquement des futures qui représentent les opérations d'entrées/sorties de bas-niveau. Les exécuteurs gèrent la planification et l'exécution des tâches. Ils assurent le suivi les tâches en cours d'exécution et celles qui sont suspendues, l'appel des futures jusqu'à ce qu'elles terminent, et réaniment les tâches lorsqu'elles peuvent progresser. Le mot "exécuteur" est souvent permuté avec "l'environnement d'exécution". Ici, nous utilisons le mot "écosystème" pour décrire un environnement d'exécution accompagné des traits et fonctionnalités compatibles.
Les crates asynchrones fournies par la communauté
La crate Futures
La crate futures
contient les traits et les
fonctions utiles pour écrire du code asynchrone. Cela comprend les traits
Stream
, Sink
, AsyncRead
, et AsyncWrite
, et des utilitaires comme les
combinateurs. Ces utilitaires et ces traits pourraient éventuellement faire
partie un jour de la bibliothèque standard.
Les futures
ont leur propre exécuteur, mais pas son propre réacteur, donc
cela ne prend pas en charge l'exécution d'entrées/sorties asynchrones ou de
futures de temporisation. C'est pour cette raison que ce n'est pas considéré
comme un environnement d'exécution complet.
Il est courant d'employer les utilitaires de futures
avec un exécuteur d'une
autre crate.
Les environnements d'exécution asynchrones populaires
Il n'y a pas d'environnement d'exécution asynchrone dans la bibliothèque standard, et aucune n'est officiellement recommandée. Les crates suivantes offrent des environnement d'exécution populaires.
- Tokio : un écosystème asynchrone populaire pour des cadriciels travaillant avec HTTP, gRPC et du traçage.
- async-std : une crate qui fournit des équivalents asynchrones aux composants de la bibliothèque standard.
- smol : un environnement d'exécution asynchrone, minimisé et simplifié.
La compatibilité des écosystèmes
Toutes les applications, cadriciels, et bibliothèques asynchrones ne sont pas compatibles entre elles, ou avec tous les systèmes d'exploitation ou plateformes. La plupart du code asynchrone peut être utilisé avec n'importe quel écosystème, mais certains cadriciels et bibliothèques nécessitent l'utilisation d'un écosystème précis. Les contraintes d'un écosystème ne sont pas toujours documentées, mais quelques méthodes empiriques pour déterminer si une bibliothèque, un trait, ou une fonction dépends d'un écosystème précis.
Tout code asynchrone qui interagit avec des entrées/sorties, temporisations,
communication inter-processus, ou des tâches asynchrones dépend généralement
d'un exécuteur ou réacteur asynchrone.
Tous les autres codes asynchrones, comme les expressions, combinateurs, types
de sychronisation, et les Stream
asynchrones sont généralement indépendants
des écosystèmes, à condition que toutes les futures imbriquées sont aussi
indépendantes de tout écosystème.
Avant de commencer un projet, il est recommandé de rechercher les cadriciels
et bibliothèques asynchrones que vous aurez besoin pour vous assurer la
compatibilité entre eux et avec l'environnement d'exécution que vous avez
choisi.
En particulier, Tokio
utilise le réacteur mio
et définit ses propres
versions des traits d'entrées/sorties asynchrones, y compris AsyncRead
et
AsyncWrite
. Seul, il n'est pas compatible avec async-std
et smol
, qui
reposent sur la crate async-executor
, et
les traits AsyncRead
et AsyncWrite
sont définis dans futures
.
Les pré-requis d'environnement d'exécution en conflit peuvent parfois être
résolus avec des couches de compatibilité qui vous permettent d'appeler du code
écrit pour un environnement d'exécution dans un autre.
Par exemple, la crate async_compat
fournit
une couche de compatibilité entre Tokio
et les autres environnements
d'exécution.
Les bibliothèques qui exposent des APIs asynchrones ne devraient pas dépendre d'un exécuteur ou d'un réacteur en particulier, à moins qu'ils aient besoin de créer des tâches ou de définir leurs propres entrées/sorties asynchrones ou des futures de temporisation. Dans l'idéal, seuls les binaires devraient être responsables de la planification et de l'exécution des tâches.
Les exécuteurs mono-processus versus multi-processus
Les exécuteurs asynchrones peuvent être mono-processus ou multi-processus.
Par exemple, la crate async-executor
a deux LocalExecutor
mono-processus et
un Executor
multi-processus.
Les exécuteurs multi-processus permettent de faire progresser plusieurs tâches en simultané. Cela peut accélérer considérablement l'exécution pour les charges de travail avec beaucoup de tâches, mais la synchronisation des données entre les tâches est habituellement moins rentable. Il est recommandé de mesurer les performances de votre application lorsque vous choisissez entre un environnement d'exécution mono-processus et multi-processus.
Les tâches peuvent être exécutées soit sur le processus qui les a créés, ou sur
processus séparé. Les environnements d'exécution asynchrones fournissent
souvent des fonctionnalités pour créer des tâches sur des processus séparés.
Même si les tâches sont exécutées sur des processus séparés, ils ne doivent
toujours pas être bloquants. Pour pouvoir planifier l'exécution des tâches sur
un exécuteur multi-processus, elles doivent être aussi être Send
. Certains
environnements d'exécution fournissent des fonctions pour créer des tâches qui
ne sont pas Send
, ce qui permet de s'assurer que les tâches sont exécutées
sur le processus qui les ont créés.
Ils peuvent également fournir des fonctions pour créer des tâches bloquantes
sur des processus dédiés, ce qui est pratique pour exécuter du code synchrone
bloquant des autres bibliothèques.