From 07463a8d58454ecff00d06e7730bce3e8fd9c1a4 Mon Sep 17 00:00:00 2001 From: Jimskapt Date: Tue, 28 Dec 2021 18:38:32 +0100 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=8C=90=20Translate=20ch09-01=20in=20f?= =?UTF-8?q?rench.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../09_02_async_tcp_server/Cargo.toml | 11 + .../09_02_async_tcp_server/src/main.rs | 20 ++ .../09_03_slow_request/Cargo.toml | 11 + .../09_03_slow_request/src/main.rs | 40 ++++ FRENCH/examples-sources/Cargo.toml | 2 + .../09_02_async_tcp_server/Cargo.toml | 11 + .../09_02_async_tcp_server/src/main.rs | 20 ++ FRENCH/examples/09_03_slow_request/Cargo.toml | 11 + .../examples/09_03_slow_request/src/main.rs | 40 ++++ FRENCH/examples/Cargo.toml | 2 + .../src/09_example/01_running_async_code.md | 211 ++++++++++++++++++ FRENCH/src/SUMMARY.md | 2 + FRENCH/src/translation-terms.md | 2 + 13 files changed, 383 insertions(+) create mode 100644 FRENCH/examples-sources/09_02_async_tcp_server/Cargo.toml create mode 100644 FRENCH/examples-sources/09_02_async_tcp_server/src/main.rs create mode 100644 FRENCH/examples-sources/09_03_slow_request/Cargo.toml create mode 100644 FRENCH/examples-sources/09_03_slow_request/src/main.rs create mode 100644 FRENCH/examples/09_02_async_tcp_server/Cargo.toml create mode 100644 FRENCH/examples/09_02_async_tcp_server/src/main.rs create mode 100644 FRENCH/examples/09_03_slow_request/Cargo.toml create mode 100644 FRENCH/examples/09_03_slow_request/src/main.rs create mode 100644 FRENCH/src/09_example/01_running_async_code.md diff --git a/FRENCH/examples-sources/09_02_async_tcp_server/Cargo.toml b/FRENCH/examples-sources/09_02_async_tcp_server/Cargo.toml new file mode 100644 index 00000000..196d1a58 --- /dev/null +++ b/FRENCH/examples-sources/09_02_async_tcp_server/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "async_tcp_server" +version = "0.1.0" +authors = ["Your Name +} +// ANCHOR_END: handle_connection_async diff --git a/FRENCH/examples-sources/09_03_slow_request/Cargo.toml b/FRENCH/examples-sources/09_03_slow_request/Cargo.toml new file mode 100644 index 00000000..aff14020 --- /dev/null +++ b/FRENCH/examples-sources/09_03_slow_request/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "slow_request" +version = "0.1.0" +authors = ["Your Name +} +// ANCHOR_END: handle_connection_async diff --git a/FRENCH/examples/09_03_slow_request/Cargo.toml b/FRENCH/examples/09_03_slow_request/Cargo.toml new file mode 100644 index 00000000..aff14020 --- /dev/null +++ b/FRENCH/examples/09_03_slow_request/Cargo.toml @@ -0,0 +1,11 @@ +[package] +name = "slow_request" +version = "0.1.0" +authors = ["Your Name + +# Exécuter du code asynchrone + +Un serveur HTTP doit être capable de servir plusieurs clients en concurrence, +et par conséquent, il ne doit pas attendre que les requêtes précédentes soient +terminées pour s'occuper de la requête en cours. +Le livre Rust [résout ce +problème](https://jimskapt.github.io/rust-book-fr/ch20-02-multithreaded.html#transformer-notre-serveur-monot%C3%A2che-en-serveur-multit%C3%A2ches) +en créant un groupe de tâches où chaque connexion est gérée sur son propre +processus. Nous allons obtenir le même effet en utilisant du code asynchrone, +au lieu d'améliorer le débit en ajoutant des processus. + + + +Modifions le `gestion_connexion` pour retourner une future en la déclarant +comme étant une fonction asynchrone : + +```rust,ignore +{{#include ../../examples/09_02_async_tcp_server/src/main.rs:handle_connection_async}} +``` + + + +L'ajout de `async` à la déclaration de la fonction change son type de retour de +`()` à un type qui implémente `Future`. + + + +Si nous essayons de compiler cela, le compilateur va nous avertir que cela ne +fonctionnera pas : + +```console +$ cargo check + Checking async-rust v0.1.0 (file:///projects/async-rust) +warning: unused implementer of `std::future::Future` that must be used + -- > src/main.rs:12:9 + | +12 | gestion_connexion(flux); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: `#[warn(unused_must_use)]` on by default + = note: futures do nothing unless you `.await` or poll them +``` + + + +Comme nous n'avons pas utilisé `await` ou `poll` sur le résultat de +`gestion_connexion`, cela ne va jamais s'exécuter. Si vous lancez le serveur et +visitez `127.0.0.1:7878` dans un navigateur web, vous constaterez que la +connexion est refusée, notre serveur ne prend pas en charge les requêtes. + + + +Nous ne pouvons pas utiliser `await` ou `poll` sur des futures dans du code +synchrone tout seul. +Nous allons avoir besoin d'un environnement d'exécution asynchrone pour gérer +la planification et l'exécution des futures jusqu'à ce qu'elles se terminent. +Vous pouvez consulter la [section pour choisir un environnement +d'exécution](../08_ecosystem/00_chapter.md) pour plus d'information sur les +environnements d'exécution, exécuteurs et réacteurs asynchrones. +Tous les environnements d'exécution listés vont fonctionner pour ce projet, +mais pour ces exemples, nous avons choisi d'utiliser la crate `async-std`. + + + +## Ajouter un environnement d'exécution asynchrone + +L'exemple suivant va monter le remaniement du code synchrone pour utiliser un +environnement d'exécution asynchrone, dans ce cas `async-std`. +L'attribut `#[async_std::main]` de `async-std` nous permet d'écrire une +fonction `main` asynchrone. +Pour l'utiliser, il faut activer la fonctionnalité `attributes` de `async-std` +dans `Cargo.toml` : + +```toml +[dependencies.async-std] +version = "1.6" +features = ["attributes"] +``` + + + +Pour commencer, nous allons changer pour une fonction `main` asynchrone, et +utiliser `await` sur la future retournée par la version asynchrone de +`gestion_connexion`. Ensuite, nous testerons comment le serveur répond. Voici à +quoi cela ressemblerait : + +```rust +{{#include ../../examples/09_02_async_tcp_server/src/main.rs:main_func}} +``` + +Maintenant, testons pour voir si notre serveur peut gérer les connexions en +concurrence. Transformer simplement `gestion_connexion` en asynchrone ne +signifie pas que le serveur puisse gérer plusieurs connexions en même temps, et +nous allons bientôt voir pourquoi. + + + +Pour illustrer cela, simulons une réponse lente. +Lorsqu'un client fait une requête vers `127.0.0.1:7878/pause`, notre serveur va +attendre 5 secondes : + + + +```rust,ignore +{{#include ../../examples/09_03_slow_request/src/main.rs:handle_connection}} +``` + +C'est très ressemblant à la [simulation d'une requête +lente](https://jimskapt.github.io/rust-book-fr/ch20-02-multithreaded.html#simuler-une-longue-requ%C3%AAte-%C3%A0-traiter-avec-limpl%C3%A9mentation-actuelle-du-serveur) +dans le livre Rust, mais avec une différence importante : +nous utilisons la fonction non bloquante `async_std::task::sleep` au lieu de la +fonction bloquante `std::thread::sleep`. +Il est important de se rappeler que même si un code est exécuté dans une +fonction asynchrone et qu'on utilise `await` sur elle, elle peut toujours +bloquer. +Pour tester si notre serveur puisse gérer les connexions en concurrence, nous +avons besoin de nous assurer que `gestion_connexion` n'est pas bloquante. + + + +Si vous exécutez le serveur, vous constaterez qu'une requête vers +`127.0.0.1:7878/pause` devrait bloquer toutes les autres requêtes entrantes +pendant 5 secondes ! +C'est parce qu'il n'y a pas d'autres tâches concurrentes qui peuvent progresser +pendant que nous utilisons `await` sur le résultat de `gestion_connexion`. +Dans la prochaine section, nous allons voir comment utiliser du code asynchrone +pour gérer en concurrence les connexions. diff --git a/FRENCH/src/SUMMARY.md b/FRENCH/src/SUMMARY.md index beeca743..1b38e2b0 100644 --- a/FRENCH/src/SUMMARY.md +++ b/FRENCH/src/SUMMARY.md @@ -1,3 +1,5 @@ # Table des matières + - [Exécuter du code asynchrone](09_example/01_running_async_code.md) + [Traduction des termes](translation-terms.md) diff --git a/FRENCH/src/translation-terms.md b/FRENCH/src/translation-terms.md index 0917f018..4c179b20 100644 --- a/FRENCH/src/translation-terms.md +++ b/FRENCH/src/translation-terms.md @@ -5,3 +5,5 @@ français. | Anglais | Français | Remarques | | ------- | ------ | ------ | +| refactoring | remaniement | - | +| snip | partie masquée ici | dans un encart | From 82354397bddfd56cd6e0241b507cfa211721ca7e Mon Sep 17 00:00:00 2001 From: Jimskapt Date: Sun, 6 Feb 2022 12:38:28 +0100 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=93=9D=20Updating=20ch09-01=20source?= =?UTF-8?q?=20until=20commit=2073cdf319ab07d7c7d4013568ce0d778370fae216.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FRENCH/examples-sources/09_03_slow_request/src/main.rs | 2 +- FRENCH/examples/09_03_slow_request/src/main.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/FRENCH/examples-sources/09_03_slow_request/src/main.rs b/FRENCH/examples-sources/09_03_slow_request/src/main.rs index 3c71ad45..60f429c3 100644 --- a/FRENCH/examples-sources/09_03_slow_request/src/main.rs +++ b/FRENCH/examples-sources/09_03_slow_request/src/main.rs @@ -33,7 +33,7 @@ async fn handle_connection(mut stream: TcpStream) { }; let contents = fs::read_to_string(filename).unwrap(); - let response = format!("{}{}", status_line, contents); + let response = format!("{status_line}{contents}"); stream.write(response.as_bytes()).unwrap(); stream.flush().unwrap(); } diff --git a/FRENCH/examples/09_03_slow_request/src/main.rs b/FRENCH/examples/09_03_slow_request/src/main.rs index 9a3ff7d4..61b3d083 100644 --- a/FRENCH/examples/09_03_slow_request/src/main.rs +++ b/FRENCH/examples/09_03_slow_request/src/main.rs @@ -33,7 +33,7 @@ async fn gestion_connexion(mut flux: TcpStream) { }; let contenu = fs::read_to_string(nom_fichier).unwrap(); - let reponse = format!("{}{}", ligne_statut, contenu); + let reponse = format!("{ligne_statut}{contenu}"); flux.write(reponse.as_bytes()).unwrap(); flux.flush().unwrap(); } From db899ebba29378b982d89b781e4cdb15708c3856 Mon Sep 17 00:00:00 2001 From: Thomas Ramirez Date: Sat, 12 Feb 2022 18:39:12 +0100 Subject: [PATCH 3/3] =?UTF-8?q?=F0=9F=90=9B=20Fix=20translation=20mistake?= =?UTF-8?q?=20in=20example=2009-03=20(ch09-01)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- FRENCH/examples/09_03_slow_request/src/main.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/FRENCH/examples/09_03_slow_request/src/main.rs b/FRENCH/examples/09_03_slow_request/src/main.rs index 61b3d083..79d1204b 100644 --- a/FRENCH/examples/09_03_slow_request/src/main.rs +++ b/FRENCH/examples/09_03_slow_request/src/main.rs @@ -26,7 +26,7 @@ async fn gestion_connexion(mut flux: TcpStream) { let (ligne_statut, nom_fichier) = if tampon.starts_with(get) { ("HTTP/1.1 200 OK\r\n\r\n", "hello.html") } else if tampon.starts_with(pause) { - task::pause(Duration::from_secs(5)).await; + task::sleep(Duration::from_secs(5)).await; ("HTTP/1.1 200 OK\r\n\r\n", "hello.html") } else { ("HTTP/1.1 404 NOT FOUND\r\n\r\n", "404.html")