Workstation dossier technique : pourquoi Rust reste une valeur par défaut forte pour de nombreuses applications modernes (API, Edge, agents et plates-formes CI/CD) et comment placer À destination de CPU fonctionner correctement à côté d’un runtime asynchrone. Nous nous inspirons (et non une réimpression textuelle) de l'essai de Alice Ryhl Async : Qu'est-ce que le blocage ?, en particulier le guidage Rayon. Compagnon: bloguer · preuve: Polyglot Benchmarks · en rapport: article polyglotte.
- Blocage (sens asynchrone) : empêcher le runtime d'échanger les tâches - généralement en passant beaucoup de temps sans
.await. - Correctif lié à CPU : préférez Rayon (ou un thread dédié) plutôt que de charger des calculs lourds sur les travailleurs Tokio.
- Bibliothèques de synchronisation liées aux IO :
tokio::task::spawn_blockingest généralement la bonne piscine. - Polyglotte: Rust est un outil puissant parmi ses pairs : mesurez avec Polyglot Benchmarks avant d'imposer une pile.
- Crédit: cadrage conceptuel inspiré de Alice Ryhl / ryhl.io ; Workstation l'applique à l'ingénierie des plateformes.
1. Les avantages Rust qui comptent dans les parcs de production
Les portefeuilles d'applications modernes sont rarement monolingues. Pourtant, certaines surfaces récompensent les propriétés du Rust :
- Sécurité de la mémoire sans gigue du GC — la propriété et l'emprunt capturent l'utilisation après libération et les courses aux données au moment de la compilation ; les chemins sensibles à la latence évitent les pauses qui arrêtent le monde.
- Performances prévisibles — Des abstractions sans coût et un contrôle précis de l'allocation rendent Rust compétitif pour les chemins API chauds et les transformations de périphérie.
- Concurrence intrépide (avec structure) — Les écosystèmes d'envoi/synchronisation et asynchrones (Tokio, modèles de traits asynchrones, canaux) encouragent les conceptions qui évoluent sous répartition.
- Binaires déployables – des artefacts statiques uniques simplifient les conteneurs pour les passerelles, les agents et les side-cars CI/CD.
- Interopérabilité dans les domaines polyglottes - FFI, Wasm et HTTP maintiennent Rust à côté des bords Go, Python, JVM et Lua sans forcer une réécriture de tout.
La position de Workstation correspond à notre Blogue Polyglot Benchmarks et long article: choisissez le bon outil pour le contexte délimité. Sur le tableau de bord en direct à polyglot-benchmarks.fictionally.org, Rust (Actix dans ce harnais) montre fréquemment de la force sur les lignes HTTP liées à CPU et sensibles à la concurrence – une preuve utile lorsqu'un ADR plaide en faveur de Rust sur un chemin chaud, et non sur une religion.
2. Planification coopérative : le sens de « blocage »
Async Rust utilise la planification coopérative. Le runtime échange les tâches lorsqu'elles atteignent un .await. La règle mémorable de Alice Ryhl s'applique partout où nous livrons des services asynchrones :
Le code asynchrone ne devrait jamais rester longtemps sans atteindre un .await.
Dans ce vocabulaire, « bloquer le thread » ne signifie pas simplement « faire des IO ». Cela signifie empêcher le runtime d'échanger la tâche en cours. Fusils classiques :
std::thread::sleepà l'intérieur d'un fn asynchrone (pas d'attente - les minuteries s'exécutent en série sousjoin!).- Boucles lourdes, compression, crypto, mathématiques vectorielles ou JSON sur stéroïdes sur un travailleur Tokio.
- Maintenir un mutex de synchronisation sur une longue section critique du pool asynchrone (les verrous courts peuvent convenir ; les verrous longs ne le sont pas).
Sur un environnement d'exécution multithread, vous pouvez masquer le bogue jusqu'à ce que vous saturiez les threads de travail. Le trafic de production le trouve pour vous. Pour les SLO de latence, traitez des dizaines à des centaines de microsecondes entre les attentes comme budget pour le travail coopératif ; tout ce qui appartient plus au pool asynchrone.
3. Trois endroits pour poser le travail qui doit bloquer
Lorsque vous devez intentionnellement bloquer un CPU coûteux ou synchroniser les E/S, déplacez ce travail hors des threads du planificateur de Tokio. L’aide-mémoire (aligné sur le cadrage de Ryhl) :
| Approche | À destination de CPU | Synchroniser les E/S | Fonctionne pour toujours |
|---|---|---|---|
spawn_blocking | Sous-optimal (grande piscine) | D'ACCORD | Non |
| Rayon | D'ACCORD | Non | Non |
Dédié std::thread | D'ACCORD | D'ACCORD | D'ACCORD |
3.1 spawn_blocking pour la synchronisation des E/S
tokio::task::spawn_blocking planifie sur le pool de blocage de Tokio (des centaines de threads par défaut). Cela convient aux appels du système de fichiers et au blocage des pilotes de base de données. Il ne convient pas au CPU soutenu, car le surabonnement combat le planificateur du système d’exploitation – parfait pour quelques calculs courts, risqué par défaut pour le traitement parallèle.
3.2 Rayon pour CPU coûteux
Rayon maintient un pool dimensionné pour le parallélisme lié à CPU. Le détail critique de l’intégration : faire pas bloquer un travailleur Tokio en attente de Rayon. Générez sur Rayon, envoyez le résultat via tokio::sync::oneshot, et .await le récepteur du côté asynchrone. Itérateurs parallèles (par_iter) j'ai encore besoin de cet extérieur rayon::spawn parce qu'ils bloquent jusqu'à la fin.
// Shape only — see ryhl.io for a full walkthrough
async fn parallel_work(data: Vec<i32>) -> i32 {
let (tx, rx) = tokio::sync::oneshot::channel();
rayon::spawn(move || {
let sum: i32 = data.into_iter().sum(); // or par_iter inside
let _ = tx.send(sum);
});
rx.await.expect("rayon task panicked")
}
Crédit : ce schéma d’intégration est au cœur du Section de caisse Rayon sur ryhl.io. Workstation recommande la même forme dans les services du produit afin que les threads de demande restent planifiables.
3.3 Threads dédiés pour un travail permanent
Une boucle qui ne se termine jamais (propriétaire de connexion DB dédiée, pont de longue durée) ne doit pas consommer un emplacement de l'un ou l'autre pool de manière permanente. Préférer std::thread::spawn et communiquer via des canaux.
4. Cartographie des conseils sur les types d'applications modernes
| Surface | Restez asynchrone | Décharger |
|---|---|---|
| API | Accepter, authentification, diffusion HTTP, streaming | Sérialisation lourde, lots cryptographiques, scoring |
| Bord/passerelles | Routage, recherche de cache, décisions WAF | Transformations CPU rares ; préfère Lua/njs lorsqu'il est mieux mesuré |
| Agents | Orchestration des outils, sessions MCP, délais d'attente | Préparation à l'intégration, suites d'évaluation, grandes transformations locales |
| Plateformes CI/CD | Promouvoir les API, les sondages sur la santé, l'interface utilisateur/API | Analyse approfondie des artefacts, vérification en masse |
Les produits Workstation illustrent cette répartition : Ring Promoter doit maintenir les portes de la promotion et de la santé vives ; WSL Proxy garde les chemins périphériques libres ; KubePilot a besoin de boucles d’incidents réactives même lorsque l’analyse est lourde. Rust (ou Go, ou Lua) est choisi par surface après mesure – jamais parce qu'un débat dans un couloir a déclaré un gagnant.
5. Liste de contrôle d'architecture pour les équipes adoptant async Rust
- L'inventaire attend des lacunes : des profileurs et des étendues de traçage qui ne cèdent jamais.
- Classifiez le travail de blocage : synchronisation IO vs CPU vs boucle éternelle.
- Choisissez la piscine :
spawn_blocking, Rayon + oneshot, ou thread dédié. - Test de charge avec une concurrence réaliste : les environnements d'exécution multithread masquent les bogues à N=1.
- Documenter la décision dans un ADR ; attachez des lignes Polyglot Benchmarks lorsque le choix de la langue est en jeu.
- Relisez les conseils Tokio sur l’état partagé et le rendement coopératif pour la latence de queue.
6. Lectures complémentaires
- Alice Ryhl — Async : Qu'est-ce que le blocage ? (inspiration principale pour le cadrage Rayon / spawn_blocking).
- Workstation — Tableau de bord en direct Polyglot Benchmarks.
- Workstation — Blog polyglotte · Article polyglotte.
- Workstation — blog compagnon pour une version écrémée de ce mémoire.
Publié par Workstation. Crédit conceptuel aux écrits publics de Alice Ryhl sur le blocage asynchrone et Rayon ; tous les cadrages de produits et conseils polyglottes sont ceux de Workstation.