From b61a91dc19b02002d1e3bf23b9c35d79514a61d1 Mon Sep 17 00:00:00 2001
From: SoTrx <-->
Date: Wed, 29 Jun 2022 16:36:46 +0200
Subject: [PATCH] [Instructions] Proofreading
---
instructions/_entries/02-04 enter dapr.md | 48 +++++++--------
instructions/_entries/02-05 without help.md | 18 +++---
instructions/_entries/03-01 intro.md | 4 +-
instructions/_entries/03-02 pub sub.md | 36 ++++++------
.../_entries/03-03 service invocation.md | 58 ++++++++++---------
instructions/_entries/03-04 bindings.md | 41 +++++++------
instructions/_entries/03-05 monitoring.md | 2 +-
instructions/_entries/04-02 create aca.md | 2 +-
8 files changed, 107 insertions(+), 102 deletions(-)
diff --git a/instructions/_entries/02-04 enter dapr.md b/instructions/_entries/02-04 enter dapr.md
index 76c94ff..5d6c9f1 100644
--- a/instructions/_entries/02-04 enter dapr.md
+++ b/instructions/_entries/02-04 enter dapr.md
@@ -5,18 +5,16 @@ title: Le role de Dapr
parent-id: lab-1
---
-Le rôle de Dapr est de permettre une sorte de découplage architecturel. Au lieu de devoir lier les composants les uns aux autres, avec l'utilisation de bibliothèques spécifiques par exemple, nous allons pouvoir ajouter un degré d'abstraction supplémentaire permettant de simplifier le code.
+Le rôle de Dapr est de permettre une sorte de découplage architecturel. Au lieu de devoir lier les composants les uns aux autres – avec l'utilisation de bibliothèques spécifiques par exemple – nous allons pouvoir ajouter un degré d'abstraction supplémentaire permettant de simplifier le code.
Plus important : ce découplage permet au développeur d'un service de se **décharger de la responsabilité de l'implémentation**.
-C'est ce que nous allons tenter d'illustrer.
+Pour illuster cela, nous allons déployer une autre version de l'application présentée qui elle utilise Dapr. Cette application se trouve dans `src/Lab1-1-decoupling/withDapr`.
-Pour cela, nous allons déployer une autre version de l'application présentée qui elle utilise Dapr. Cette application se trouve dans `src/Lab1-1-decoupling/withDapr`.
-
-Cette nouvelle version est exécutable en utilisant la command suivante:
+Cette nouvelle version est exécutable en utilisant la commande suivante:
```shell
-# Si make installé
+# Si make est installé
make run
# Sinon
docker-compose up
@@ -27,7 +25,7 @@ docker-compose up
Solution :
{% collapsible %}
-Un appel HTTP générique est effectué sur le port 3500 **de l'interface localhost** du service. Ce port est le port par défaut de Dapr.
+Un appel HTTP générique est effectué sur le port 3500 **de l'interface localhost** du service. Ce port est celui utilisé par défaut par Dapr.
```ts
// src/Lab1/1-decoupling/withDapr/node/src/app.ts, line 9
@@ -36,13 +34,13 @@ const stateStoreName = `statestore`;
const stateUrl = `http://localhost:${daprPort}/v1.0/state/${stateStoreName}`;
```
-En effet, Dapr fonctionne avec le principe du `sidecar`. Chaque service (application principale) que nous allons déployer va être accompagné d'une instance de Dapr (sidecar) qui s'execute dans la même "sandbox applicative" (~= l'interface localhost est partagée).
+En effet, Dapr fonctionne avec le principe du `sidecar`. Un sidecar est un petit programme qui va venir se greffer sur chacun des services que nous allons déployer. Chaque couple (application principale, sidecar) partage la même interface localhost.
-À chaque fois que l'application principale voudra effectuer une communication vers une autre service, elle pourra se contenter d'appeller son sidecar, qui lui se chargera de transmettre l'appel
+À chaque fois que l'application principale voudra effectuer une communication vers un autre service, elle pourra se contenter d'appeller son sidecar, qui lui se chargera à son tour de transmettre l'appel
{% endcollapsible %}
-> **Question** : Dans le fichier `docker-compose.yml`, où sont les "sidecars" Dapr ? Comment partagent-ils leur interface localhost avec leurs applications principales ? Le conteneur Redis a t-il un sidecar ?
+> **Question** : Dans le fichier `docker-compose.yml`, où sont les *sidecars* Dapr ? Quelle est l'instruction docker-compose leur permettant à chaque *sidecar* d'accéder à l'interface localhost du service auquel il est attaché ? Le conteneur Redis a t-il un sidecar ?
Solution:
{% collapsible %}
@@ -81,16 +79,16 @@ Solution:
network_mode: "service:nodeapp"
```
-Le conteneur Redis n'a pas de sidecar, puisque ce n'est pas un service mais seulement un moyen de communication. Il n'a pas besoin des fonctionnalités apportées par Dapr
+Le conteneur Redis n'a pas de sidecar, puisque ce n'est pas un service mais seulement un moyen de communication (ou support de stockage). Il n'a pas besoin des fonctionnalités apportées par Dapr
{% endcollapsible %}
-> **Question**: Toujours dans le `docker-compose.yml`, on peut remarquer qu'un volume nommé **components** est monté sur chacun des sidecars, que contient le dossier ? Quelle peut être l'utilisé du contenu ?
+> **Question**: Toujours dans le `docker-compose.yml`, on peut remarquer qu'un [volume](https://docs.docker.com/storage/volumes/) nommé **components** est monté sur chacun des sidecars, que contient le dossier ? Quelle peut être l'utilité des fichiers qu'il contient ?
Solution:
{% collapsible %}
-Ce dossier contient un fichier .yml ressemblant à ceci.
+Ce dossier contient un fichier yaml ressemblant à ceci.
```yml
apiVersion: dapr.io/v1alpha1
@@ -111,11 +109,13 @@ spec:
value: ""
```
-Il s'agit d'une définition d'un **[composant](https://docs.dapr.io/concepts/components-concept/** Dapr. Ces composants sont une idée centrale de Dapr et ce sont eux qui permettent cette notion de découplage.
+Il s'agit d'une définition d'un **[composant](https://docs.dapr.io/concepts/components-concept/)** Dapr.
+
+Ces composants sont une idée centrale de Dapr et ce sont eux qui permettent cette notion de découplage.
Ici, on annonce déclarativement que l'on veut utiliser Redis en tant que composant de stockage d'état.
Grâce à cette déclaration, tous les appels que les applications feront pour récupérer ou stocker un état seront
-redirigé vers Redis.
-Il suffirait de changer ce composant pour changer la déclaration.
+redirigés vers Redis.
+Il suffirait de changer ce composant pour changer le support de stockage sous-jacent.
{% endcollapsible %}
@@ -129,28 +129,28 @@ Le chemin parcouru par notre état est le suivant :
```bash
# On retrouve dans l'URL l'id spécifié dans le sidecar du service Node.
-# Cette url a pour but d'invoquer la méthode "neworder" sur le service "nodeapp"
-# Nous verrons cela en détails dans le second lab
+# Cette URL a pour but d'invoquer la méthode "neworder" sur le service "nodeapp"
+# Nous verrons cela en détail dans le second lab
http://localhost:3500/v1.0/invoke/nodeapp/method/neworder
```
- Le sidecar du service python communique l'état au sidecar du service donc `-l'app-id` est celui spécifié dans l'URL, ici **nodeapp**
- Le sidecar du service Node transmet l'état au service Node
-- le service node indique à son sidecar qu'il veut stocker un état dans le composant de stockage nommé {{storename}} avec un appel de la forme
+- le service node indique à son sidecar qu'il veut stocker un état dans le composant de stockage nommé **storename** avec un appel de la forme
```shell
-POST /state/{{storename}}
+POST /state/storename
```
-- Dapr regarde alors ses composants et récupère le composant de gestion d'état de nom {{storename}}. Ce composant specifie l'hôte et les paramètres de connexion de l'implémentation du composant, ici Redis. L'appel est ensuite transféré vers Redis.
+- Dapr regarde alors ses composants et récupère le composant de gestion d'état de nom **storename**. Ce composant specifie l'hôte et les paramètres de connexion de l'implémentation du composant, ici Redis. L'appel est ensuite transféré vers Redis.
> **En Pratique** : En vous servant [de la documentation dediée](https://docs.dapr.io/reference/components-reference/supported-state-stores/setup-mongodb/), migrez le gestionnaire de message de Redis à MongoDB
-**Indication** : La base de données mongo est déjà présente dans le fichier `docker-compose.yml`, il faut l'utiliser
+**Indication** : La base de données MongoDB est déjà présente dans le fichier `docker-compose.yml`, il faut simplement l'utiliser
Solution:
{% collapsible %}
-Pour changer le gestionnaire d'état de Redis vers MongoDb, il faut simplement changer le composant dédié, `src/Lab1/1-decoupling/withDapr/components/statestore.yaml`
+Pour changer le gestionnaire d'état de Redis vers MongoDB, il faut simplement changer le composant dédié, `src/Lab1/1-decoupling/withDapr/components/statestore.yaml`
En l'état le composant utilise Redis :
@@ -169,7 +169,7 @@ spec:
value: ""
```
-Changer simplement le type du composant en mongodb et les identifiants d'accès permet de changer de gestionnaire d'état:
+Changer simplement le type du composant en MongoDB et les identifiants d'accès permet de changer de gestionnaire d'état:
```yml
apiVersion: dapr.io/v1alpha1
diff --git a/instructions/_entries/02-05 without help.md b/instructions/_entries/02-05 without help.md
index 8eaa40a..93cbe06 100644
--- a/instructions/_entries/02-05 without help.md
+++ b/instructions/_entries/02-05 without help.md
@@ -1,27 +1,27 @@
---
sectionid: lab1-withouthelp
sectionclass: h2
-title: Le mode processus
+title: Le mode processus (Facultatif)
parent-id: lab-1
---
Dans les exercices précédents, nous avons surtout travaillé avec des conteneurs, un fichier `docker-compose.yml` étant même fourni.
-Il est cependant possible d'utiliser Dapr en mode processus, ce qui permet un processus de développement plus simple
+Il est cependant possible d'utiliser Dapr en mode processus, ce qui permet un processus de développement/débuggage plus simple
> **En pratique** : Installez Dapr localement sur votre PC et initialisez votre environnement local.
**Indication** : [Documentation](https://docs.dapr.io/getting-started/). Ne pas intialiser Dapr pour un environnement Kubernetes !
-> **Question** : Quels sont les conteneurs déployés par l'initilisation de Dapr ? Quel est le rôle de chacun ?
+> **Question** : Quels sont les conteneurs déployés par l'initialisation de Dapr ? Quel est le rôle de chacun ?
Solution:
{% collapsible %}
Les conteneurs déployés sont :
-- Redis : En initialisant Dapr, une instance de Redis ainsi que le composant associé sont crées (dans le répertoire `~/.dapr/components`). Redis pouvant à la fois assurer les fonctionnalités de persistence d'état et de distribution de message, il est souvent choisi comme composant par défaut **dans les environnements de développement**
-- Zipkin : [Logiciel Open-Source](https://github.com/openzipkin/zipkin) permettant de tracer les appels entre les services (Nous y reviendrons dans le _Lab2_)
-- Placement : Un service de Dapr permettant d'utiliser le [modèle de programmation distribuée "Acteurs"](https://docs.dapr.io/developing-applications/building-blocks/actors/actors-overview/). Vous pourrez retrouver une explictaion détaillé du principe de ce modèle [ici](https://github.com/dotnet/orleans)
+- Redis : En initialisant Dapr, une instance de Redis ainsi que le composant associé sont créés (dans le répertoire `~/.dapr/components`). Redis pouvant à la fois assurer les fonctionnalités de persistence d'état et de distribution de message, il est souvent choisi comme composant par défaut **dans les environnements de développement**.
+- Zipkin : [Logiciel Open-Source](https://github.com/openzipkin/zipkin) permettant de tracer les appels entre les services (Voir _Lab2_)
+- Placement : Un service de Dapr permettant d'utiliser le [modèle de programmation distribuée "Acteurs"](https://docs.dapr.io/developing-applications/building-blocks/actors/actors-overview/). Vous pourrez retrouver une explication détaillée du principe de ce modèle [sur le GitHub du projet Orléans](https://github.com/dotnet/orleans)
{% endcollapsible %}
### Déployer une application en mode processus
@@ -46,7 +46,7 @@ Puisque le type de déploiement que nous visons n'est pas conteneurisé, il va t
Solution:
{% collapsible %}
-Après avoir effectué les étapes d'installations, il suffit de lancer les commandes
+Après avoir effectué les étapes ci-dessus, il suffit de lancer les commandes
```shell
# cwd: src/Lab2/1-without-help/node
@@ -60,8 +60,8 @@ dapr run --app-id pythonapp --components-path ../components -- python app.py
### Récapitulatif
-Dapr permet à la fois d'assister des applications conteneurisées (pattern du sidecar) mais aussi d'exécuter des processus.
+Dapr permet à la fois d'assister des applications conteneurisées (pattern du sidecar) mais aussi des applications en mode processus.
Si la partie sidecar est indiquée dans des cas d'orchestration de conteneurs (Kubernetes, docker-compose, docker swarm...), la partie processus va nous permettre d'exécuter des applications localement sans avoir à penser à les conteneuriser.
-Ces deux modes de fonctionnement assurent une compatibilité avec des services Cloud comme du Kubernetes Managé (AKS) ou simplement de l'hébergement d'application en mode process (App Service\*)
+Ces deux modes de fonctionnement assurent une compatibilité avec des services Cloud comme du Kubernetes Managé (AKS) ou simplement de l'hébergement d'application en mode process (App Service)
diff --git a/instructions/_entries/03-01 intro.md b/instructions/_entries/03-01 intro.md
index 8d46fda..649b0b0 100644
--- a/instructions/_entries/03-01 intro.md
+++ b/instructions/_entries/03-01 intro.md
@@ -7,8 +7,8 @@ parent-id: lab-2
Dans ce deuxième Lab, nous allons voir d'autres fonctionnalités ajoutées par Dapr, à travers une nouvelle application qui évoluera au fur et à mesure des exercices.
-Cette nouvelle application va permettre de précommander un produit, et a une particularité, tous ses services sont codés dans des langages différents.
+Cette nouvelle application va permettre de précommander un produit très spécifique. Elle a également une particularité, tous ses services sont codés dans des langages différents.
Les implémentations des différents services utilisés sont données à titre d'information dans le dossier `src/Lab2/implementations`.
-Il faut cependant noter que le but de cet exercice n'est pas de s'intéresser au code mais plutôt de voir comment on peut obtenir un niveau de service équivalent devoir chercher ou concevoir des équivalences entres les langages.
\ No newline at end of file
+Il faut cependant noter que le but de cet exercice n'est pas de s'intéresser au code des services mais plutôt de voir comment on peut obtenir un niveau de service équivalent indépendamment des langages utilisés.
\ No newline at end of file
diff --git a/instructions/_entries/03-02 pub sub.md b/instructions/_entries/03-02 pub sub.md
index a6f6074..2f67a5e 100644
--- a/instructions/_entries/03-02 pub sub.md
+++ b/instructions/_entries/03-02 pub sub.md
@@ -18,14 +18,14 @@ On va retrouver dans ce mode de communication deux types d'acteurs:
- des **Producteurs** (_Publishers_), qui produisent un contenu, souvent des messages
- des **Consommateurs** (_Subscribers_), qui attendent du contenu
-Si une invocation directe peut par analogie est considéré comme un appel téléphonique, le _pub/sub_ serait une boîte mail, que chacun peut consulter comme bon lui semble.
+Par analogie, si une invocation directe pourrait être considérée comme un appel téléphonique, le _pub/sub_ serait alors une boîte mail, que chacun pourrait consulter quand bon lui semble.
La majorité du temps, le pub/sub fonctionne en **_one to many_**, c'est à dire qu'un message d'un producteur va parvenir à tous les consommateurs. Il existe cependant des configurations **_one to one_**, où un message d'un producteur n'est reçu que par un seul consommateur.
{% endcollapsible %}
### Dapr
-A l'aide de la [documentation](https://docs.dapr.io/developing-applications/building-blocks/pubsub/), nous allons nous intéresser à ces questions
+A l'aide de la [documentation](https://docs.dapr.io/developing-applications/building-blocks/pubsub/), nous allons nous intéresser à ces questions:
> **Question** : Comment fonctionne la fonctionnalité PUB/SUB de Dapr ? Quel est le chemin d'un message depuis son envoi d'un service A vers un service B ?
@@ -35,27 +35,27 @@ Solution :
En reprenant l'image de la documentation, on peut voir que:
- le message passe du service à son sidecar
-- le sidecar résoud le composant, et redirige le message vers l'implémentation
+- le sidecar résoud le composant, et redirige le message vers l'implémentation sous-jacente
- l'implémentation notifie tous les sidecars avec le contenu du message
- les sidecars redirigent le contenu du message vers une route HTTP de leurs services respectifs
{% endcollapsible %}
> **Question** : Quelle est la garantie de livraison associée à la fonctionnalité de PUB/SUB ? Quels sont les avantages et les incovénients ?
-> Solution :
+Solution :
{% collapsible %}
La garantie est **at least once**. ([Lien dans la documentation](https://docs.dapr.io/developing-applications/building-blocks/pubsub/pubsub-overview/#at-least-once-guarantee)).
Cette garantie signifie que chaque message envoyé par un producteur sera reçu au moins une fois par chaque consommateur.
-L'avantage est qu'il n'est pas possible de perdre un message, du tout du moins si un moins un consommateur est inscrit au momment de l'envoi du message.
+L'avantage est qu'il n'est pas possible de perdre un message, tout du moins dès lors qu'au moins un consommateur est inscrit au moment de l'envoi du message.
L'inconvénient principal est qu'il est possible de recevoir plusieurs fois le même message.
Cet inconvénient peut se traiter applicativement. Un exemple est de retenir l'ID des X derniers messages traités, ou simplement d'avoir un service resistant par conception à la duplication.
##### Pour aller plus loin
-Lors de la conception d'un système de communication, si la possibilité de duplication est absolument à éviter il faudra plutôt s'orienter vers une garantie **at most once**. Un message sera alors livré au plus une fois, ce qui évitera la duplictaion mais pourra occasioner des pertes de messages.
+Lors de la conception d'un système de communication, si la possibilité de duplication est absolument à éviter il faudra plutôt s'orienter vers une garantie **at most once**. Un message sera alors livré au plus une fois, ce qui évitera la duplictaion mais pourra occasionner des pertes de messages.
-La garantie idéale, **exactly once** n'est pas proposée dans le cas général. En effet, il existera toujours un cas limite où il faudra relancer la transaction (comsommateur qui crash pendant la reception d'un message...).
+La garantie idéale, **exactly once**, n'est pas proposée dans le cas général. En effet, il existera toujours un cas limite où il faudra relancer la transaction (comsommateur qui échoue pendant la reception d'un message...).
{% endcollapsible %}
@@ -65,7 +65,7 @@ Solution :
{% collapsible %}
-Pour souscrire à un _topic_, Dapr propose deux méthodes
+Pour souscrire à un _topic_, Dapr propose deux méthodes:
##### Dans le code
@@ -142,7 +142,7 @@ scopes:
Cette fonctionnalité est pensée dans les cas où l'appplication reçoit un grand nombre d'événements différents. Elle permet :
- d'empêcher de créer un grand nombre de topics, un pour chaque cas limite de l'application. Sur le Cloud public, cela résoud notamment une problématique de coût.
-- d'éviter à l'application elle-même de faire le routage, ce qui entraîne une complexité inutile.
+- d'éviter à l'application elle-même de faire le routage, ce qui entraînerait une complexité inutile.
Il faut cependant noter que l'abus de cette fonctionnalité pourrait entraîner une difficulté de compréhension des flux de l'application. La meilleure manière d'éviter une telle situation est de prévoir son utilisation dès l'étape de conception.
{% endcollapsible %}
@@ -153,7 +153,7 @@ Voici l'état actuel de l'application de pré-commande fil rouge :
![Step 0](/media/lab2/app-step-0.png)
-Le frontend va être la vitrine de notre site, qui s'exécute sur le navigateur du client (raison pour laquelle il n'a pas de sidecar Dapr rattaché, non réaliste) et l'API la porte d'entrée de l'architecture du backend.
+Le frontend va être la vitrine de notre site, qui s'exécute sur le navigateur du client (raison pour laquelle il n'a pas de sidecar Dapr rattaché) et l'API la porte d'entrée de l'architecture du backend.
L'application peut être lancée en se rendant le dossier `src/Lab2/1-pub-sub` puis en lançant la commande
@@ -202,9 +202,9 @@ spec:
value: ""
```
-Il s'agit du composant dapr faisant le lien avec l'implémentation du pubsub, ici redis.
+Il s'agit du composant Dapr faisant le lien avec l'implémentation du pubsub, ici Redis.
-Le nom du composant, (la valeur de la clef du yaml **metadata.name**) est `order-pub-sub`.
+Le nom du composant (la valeur de la clef du yaml **metadata.name**) est `order-pub-sub`.
Attention à ne pas confondre ce nom avec le nom du fichier qui lui est simplement pubsub.
{% endcollapsible %}
@@ -213,7 +213,7 @@ Attention à ne pas confondre ce nom avec le nom du fichier qui lui est simpleme
**Indice** : L'URL qui permet à **command-api** de publier un message est un appel vers son sidecar. L'API pub/sub de Dapr est détaillée [ici](https://docs.dapr.io/reference/api/pubsub_api/).
-**Indice 2** : Il n'est **pas demandé** de faire des modifications dans le code des services ! Souvenez-vous qu'il existe plusieurs manière de souscrire à un *topic*
+**Indice 2** : Il n'est **pas demandé** de faire des modifications dans le code des services ! Souvenez-vous qu'il existe plusieurs manières de souscrire à un *topic*
Solution :
@@ -223,7 +223,7 @@ Parmi ces deux services, **command-api** est le producteur. Comme les SDKs ne so
##### Command API
-Le service **command-api** est le producteur. Pour pouvoir publier un événement, il a besoin de l'URL vers laquelle publier.
+Le service **command-api** est le producteur. Pour pouvoir publier un événement, il a besoin de l'URL vers laquelle publier son contenu.
Cette URL peut se trouver dans la [documentation](https://docs.dapr.io/reference/api/pubsub_api/), et est de la forme :
@@ -244,7 +244,7 @@ Une fois les variables remplies, l'URL d'invocation est donc
http://localhost:3500/v1.0/publish/order-pub-sub/orders
```
-Il ne reste plus qu'à renseigner cette url dans les variables d'environnements du fichier `src/Lab2/1-pub-sub/docker-compose.yml`
+Il ne reste plus qu'à renseigner cette URL dans les variables d'environnements du fichier `src/Lab2/1-pub-sub/docker-compose.yml`
```diff
...
@@ -272,7 +272,7 @@ A l'aide des questions précédentes, nous savons qu'il existe deux méthodes po
- par le code
- déclarativement
-Le choix ici est rapide : puisqu'il n'est aps demandé de faire des modifications dans le code des services, nous allons utiliser la méthode **déclarative**.
+Le choix ici est rapide : puisqu'il n'est pas demandé de faire des modifications dans le code des services, nous allons utiliser la méthode **déclarative**.
Pour cela, nous devons [créer un yaml représentant la souscription](https://docs.dapr.io/developing-applications/building-blocks/pubsub/subscription-methods/) dans le dossier `src/Lab2/1-pub-sub/components/`. Le nom du fichier n'a aucune importance.
@@ -303,8 +303,8 @@ scopes:
> **En pratique**: Implémenter le PUB/SUB entre `command-api` et `order-processing`
-Une trace indiquant le success devrait avoir cette forme après avoir lancé une commande
+Une trace indiquant le succès devrait avoir cette forme
![expected result](/media/lab2/pubsub/expected-result.png)
-**Note 1**: Dans un pattern Pub/Sub, un message est supprimé d'un _topic_ après que tous les consommateurs de ce topic l'ai reçu. Dans une véritable application E-commerce, où les microservices peuvent éventuellement _scaler_, c'est à dire multiplier leur nombre d'instances, les commandes pourraient être traitées plusieurs fois. La bonne approche dans ce genre de cas est d'utiliser une file de message, où le message sera supprimé après la première lecture.
+**Note 1**: Dans un pattern Pub/Sub, un message est supprimé d'un _topic_ après que tous les consommateurs de ce topic l'ai reçu. Dans une véritable application E-commerce, où les microservices peuvent éventuellement _scaler_, c'est à dire augmenter leur nombre d'instances, les commandes pourraient être traitées plusieurs fois. La bonne approche dans ce genre de cas est d'utiliser une file de message, où le message serait supprimé après le premier traitement.
diff --git a/instructions/_entries/03-03 service invocation.md b/instructions/_entries/03-03 service invocation.md
index d98babc..5796a5d 100644
--- a/instructions/_entries/03-03 service invocation.md
+++ b/instructions/_entries/03-03 service invocation.md
@@ -7,7 +7,7 @@ parent-id: lab-2
### Généralités
-> **Question généraliste**: Qu'est-ce que le _Service Meshing_ ? Quels sont les exemples de logiciels proposant cette fonctionnalité ?
+> **Question généraliste**: Qu'est-ce que le _Service Meshing_ ? Quels sont les exemples de logiciels proposants cette fonctionnalité ?
Solution :
{% collapsible %}
@@ -53,8 +53,8 @@ C'est de cette particuliarité que proviennent les avantages du _gRPC_, la vites
Les inconvénients principaux sont :
-- le _gRPC_ est bien plus difficile à interpréter pour un humain que le REST, en faisant une solution plutôt préférée pour la communication service backend à service backend
-- le temps de développement _gRPC_ est accru
+- le _gRPC_ est bien plus difficile à interpréter pour un humain que le REST, en faisant une solution plutôt préférée pour la communication service de backend à service backend
+- le temps de développement _gRPC_ est plus long
{% endcollapsible %}
### Dapr
@@ -65,7 +65,7 @@ A l'aide de la [documentation](https://docs.dapr.io/developing-applications/buil
Solution :
{% collapsible %}
-Le principe de l'invocation de service est de pouvoir invoquer une méthode d'un service distant de manière sécurisé et résiliente. Invoquer un service permet également à Dapr de générer automatiquement logs et traces.
+Le principe de l'invocation de service est de pouvoir invoquer une méthode d'un service distant de manière sécurisée et résiliente. Invoquer un service permet également à Dapr de générer automatiquement les logs et les traces.
Un paquet allant du service A au service B aurait donc le trajet:
@@ -110,13 +110,13 @@ Solution:
Le Service Meshing se déploie sur une infrastructure, et est unique à cette infrastructure. C'est une fonctionnalité OPS.
L'invocation de service de Dapr est indépendante de l'infrastructure, elle concerne le DEV.
-Sur les foctionnalités:
+Sur les fonctionnalités:
Si un Service Meshing et l'invocation de Service de Dapr permettent tous les deux de faciliter les appels de service à service, le service meshing va travailler au niveau du réseau, tandis que Dapr va travailler au niveau de l'application. Il en suit :
- Dapr **ajoute** une découverte des méthodes de l'application en plus de résoudre le nom du service
-- Dapr **ne permettra pas** de redirections réseau à travers Internet (ou un tunnel) dans un cas d'application cross-cloud par exemple.
+- Dapr **ne permettra pas** de redirections réseau à travers Internet (ou un tunnel) dans un cas d'application multi-clouds par exemple.
-Il est donc possible d'utiliser un service comme _Istio_ en conjonction avec Dapr, les services n'ayant pas la même couverture fonctionnelle
+Il est donc possible d'utiliser un service comme _Istio_ en conjonction avec Dapr, les services n'ayant pas la même couverture fonctionnelle.
Voir https://docs.dapr.io/concepts/service-mesh/
{% endcollapsible %}
@@ -126,26 +126,26 @@ Voir https://docs.dapr.io/concepts/service-mesh/
Solution:
{%collapsible %}
-Sentry permet le **chiffrage** et **l'authentification mutuelle** des communications entre services. Il permet la communication mTLS entre les services, agissant comme un stockage / broker de certificats.
+Sentry permet le **chiffrage** et **l'authentification mutuelle** des communications entre services. Il permet la communication mTLS entre les services, agissant alors en tant que stockage / broker de certificats.
-Sentry est un service totalement optionnel. S'il n'est pas présent au démarrage des sidecars (et son adresse spécifié dans la commande de démarrage), les communications ne seront pas chiffrées.
+Sentry est un service totalement optionnel. S'il n'est pas présent au démarrage des *sidecars* (et son adresse spécifiée dans la commande de démarrage), les communications ne seront simplement pas chiffrées.
Dapr possède donc une architecture modulaire, et il existe d'autres services optionnels :
-- **[Placement](https://docs.dapr.io/concepts/dapr-services/placement/)** est un service optionnel permettant l'utilisation du [modèle Acteurs](https://fr.wikipedia.org/wiki/Mod%C3%A8le_d%27acteur)
-- Le **[DNS](https://docs.dapr.io/reference/components-reference/supported-name-resolution/)** interne à Dapr est aussi modulaire. Par défaut, une résolution plate (mDNS) est utilisée, mais **coreDNS**(Kubernetes) ou bien **Consul** peuvent être utilisés selon les plateformes.
+- **[Placement](https://docs.dapr.io/concepts/dapr-services/placement/)**, permettant l'utilisation du [modèle Acteurs](https://fr.wikipedia.org/wiki/Mod%C3%A8le_d%27acteur)
+- Le **[Name Resolution Component](https://docs.dapr.io/reference/components-reference/supported-name-resolution/)** interne à Dapr est aussi modulaire. Par défaut, une résolution plate ([mDNS](https://en.wikipedia.org/wiki/Multicast_DNS)) est utilisée, mais **coreDNS**(Kubernetes) ou bien **Consul** peuvent également être utilisés selon les plateformes.
{% endcollapsible %}
### En application
-> Note : La nouvelle version de l'application se trouve désormais dans `src/Lab2/2-service-invocation`
+> **Note** : La nouvelle version de l'application se trouve désormais dans `src/Lab2/2-service-invocation`
-Il est l'heure de reprendre le fil rouge. Cherchant toujours à rendre notre application de pré-commande complète, deux nouveaux services sont ajoutés, toujours dans des langages différents:
+Il est l'heure de reprendre le fil rouge. Cherchant toujours à rendre notre application de pré-commandes complète, deux nouveaux services ont été ajoutés:
-- **stock-manager** (en Go): Une fois une commande validée par **order-processing**, celui-ci appelle la méthode _/stock_ de **stock-manager** pour qu'il rajoute la commande aux stocks requis.
-- **receipt-generator** (en Rust): Une fois une commande validée par **order-processing**, celui-ci appelle la méthode _/_ de **receipt-generator** afin qu'il génère une confirmation
+- **stock-manager** (en Go): Une fois une commande validée, **order-processing** appelle la méthode _/stock_ de **stock-manager** pour qu'il rajoute la commande aux stocks requis.
+- **receipt-generator** (en Rust): Une fois une commande validée, **order-processing** appelle la méthode _/_ de **receipt-generator** afin qu'il génère une confirmation
-Les deux services seront appelés par **order-processing**. Le nom de chaque service est également son ID.
+Le nom de chaque service est également son app-id.
La nouvelle cible est donc:
@@ -153,7 +153,7 @@ La nouvelle cible est donc:
> **Question**: Quelle est l'URL que doit utiliser **order-processing** pour appeler **stock-manager** ? Expliquez.
-**Indice** : L'API d'invocation de service de Dapr est disponible [ici](https://docs.dapr.io/reference/api/service_invocation_api/)
+**Indice** : L'API d'invocation de Dapr est disponible [ici](https://docs.dapr.io/reference/api/service_invocation_api/)
Solution :
{% collapsible %}
@@ -165,10 +165,10 @@ PATCH/POST/GET/PUT/DELETE http://localhost:3500/v1.0/invoke//method/ est l'id du service à appeler tel que déclaré par le l'option `--app-id` de la ligne de commande de Dapr
-- est le nom de la méthode à appeler sur le service distant
+- **localhost:3500** est l'adresse du sidecar
+- **invoke** est le préfixe de l'API d'invocation
+- **\** est l'id du service à appeler tel que déclaré par le l'option `--app-id` de la ligne de commande de Dapr
+- **\** est le nom de la méthode à appeler sur le service distant
Dans ce cas précis, le service à appeler est **stock-manager**, plus particulièrement la méthode _/stock_
@@ -192,10 +192,10 @@ PATCH/POST/GET/PUT/DELETE http://localhost:3500/v1.0/invoke//method/ est l'id du service à appeler tel que déclaré par le l'option `--app-id` de la ligne de commande de Dapr
-- est le nom de la méthode à appeler sur le service distant
+- **localhost:3500** est l'adresse du sidecar
+- **invoke** est le préfixe de l'API d'invocation
+- **\** est l'id du service à appeler tel que déclaré par le l'option `--app-id` de la ligne de commande de Dapr
+- **\** est le nom de la méthode à appeler sur le service distant
Dans ce cas précis, le service à appeler est **receipt-generator**, plus particulièrement la méthode _/_
@@ -207,7 +207,13 @@ http://localhost:3500/v1.0/invoke/receipt-generator/method/
{% endcollapsible %}
-> **En pratique**: A l'aide des deux questions précédentes, renseignez les variables d'environnements **RECEIPT_GENERATOR_INVOKE_URL** et **STOCK_MANAGER_INVOKE_URL** dans `docker-compose.yml`. Executez le fichier docker-compose et lancer une commande via l'interface.
+> **En pratique**: A l'aide des deux questions précédentes, renseignez les variables d'environnements **RECEIPT_GENERATOR_INVOKE_URL** et **STOCK_MANAGER_INVOKE_URL** dans `docker-compose.yml`. Exécutez le fichier docker-compose et lancer une pré-commande via l'interface web (localhost:8089).
+
+**Rappel**: Pour lancer un fichier docker-compose, lancez la commande suivante
+
+```sh
+docker-compose rm -fsv ; docker-compose up
+```
La trace de succès devrait avoir cette forme :
![Expected result](/media/lab2/service-invocation/expected-result.png)
diff --git a/instructions/_entries/03-04 bindings.md b/instructions/_entries/03-04 bindings.md
index 34c4eee..ee03de3 100644
--- a/instructions/_entries/03-04 bindings.md
+++ b/instructions/_entries/03-04 bindings.md
@@ -7,25 +7,26 @@ parent-id: lab-2
### Généralités
-> **Question généraliste** : Qu'est-ce qu'une _architecture orientée services_ ? Qu'est-ce qu'une architecture orientée événements\* ? Quelle est la différence entre les deux ?
+> **Question généraliste** : Qu'est-ce qu'une architecture orientée services ? Qu'est-ce qu'une architecture orientée événements ? Quelle est la différence entre les deux ?
Solution:
{%collapsible %}
**/!\ Approximations /!\\**
-Une architetcure orientée services (SOA) est une architecture où une tâche à accomplir est répartie entre plusieurs programmes (services) s'appelant les uns les autres. Selon la part de responsabilité de chaque services, on peut les appeler microservices.
+
+Une architetcure orientée services (SOA) est une architecture où une tâche à accomplir est répartie entre plusieurs programmes (services) s'appelant les uns les autres. Selon la part de responsabilité de chaque service, on peut les appeler microservices.
Une architecture orientée événement (EDA) est une architecture où la communication entre les composantes d'une application (qui peuvent être des services) est assurée au travers d'événements. Ces événements transitent généralement par des **bus d'événements**.
Deux différences importantes entre les deux :
- **Couplage**
- - En SOA les services sont couplés plus ou moins fortements (url à appeller, file de message...)
+ - En SOA les services sont couplés plus ou moins fortements (URLs, files de messages...)
- En EDA le couplage est lâche, ceux publiant des événements ne savent pas qui les écoutent et réciproquement
- **Cohérence**:
- - En SOA quand un service A appelle un Service B, l'état de Service A ne change que si l'appel à Service B est réussi (ex : HTTP 200)
- - En EDA quand un service A publie un événement et qu'un service B l'écoute, l'état de service A a déjà changé au moment de la publication, puisqu'il n'y a pas de retour de service B
+ - En SOA quand un service A appelle un Service B, l'état de Service A ne change qu'après le succès de l'appel (ex : HTTP 200)
+ - En EDA quand un service A publie un événement et qu'un service B l'écoute, l'état de service A a déjà changé au moment de la publication, puisqu'il n'y a pas de retour du service B
-Nous avons vu deux manière de pouvoir approcher la communication avec les deux derniers exercices, il reste maintenant la communication externe.
+Nous avons vu deux manières de pouvoir approcher la communication avec les deux derniers exercices, il reste maintenant la communication externe.
{% endcollapsible %}
@@ -34,15 +35,15 @@ Nous avons vu deux manière de pouvoir approcher la communication avec les deux
A l'aide de la [documentation](https://docs.dapr.io/developing-applications/building-blocks/bindings/bindings-overview/), nous allons nous intéresser à ces questions
> **Question** : Quelle est l'utilité d'un _binding_ ?
-> Solution:
+Solution:
{%collapsible %}
Un binding est simplement un moyen d'intéragir avec un système en dehors de notre périmètre applicatif.
Le principe est simplement de lier un nom à un système externe et de pouvoir appeller ce nom dans les services de l'application.
-L'avantage est que cet appel est réalisé de manière transparente, le service appelant se sait pas (et ne devrait pas savoir) que le système appelé par le binding est externe.
+L'avantage est que cet appel est réalisé de manière transparente, le service appelant ne sait pas (et ne devrait pas savoir) que le système appelé par le binding est externe.
{% endcollapsible %}
@@ -51,7 +52,6 @@ L'avantage est que cet appel est réalisé de manière transparente, le service
Solution:
{%collapsible %}
-
##### Input binding
Un _input binding_ permet de réagir à un changement d'état d'un système externe.
@@ -62,27 +62,27 @@ Un exemple serait de réagir à un nouveau message sur une file de message situ
Un _output binding_ permet de faire réagir un système externe à un changement d'état de notre application
-Un exemple serait de définir un binding vers un fournisseur de mail. Au lieu d'avoir un service dédiée directement dans l'application, ce binding pourrait être appelé par tous les services en ayant besoin.
+Un exemple serait de définir un binding vers un fournisseur de mail. Au lieu d'avoir un service dédié dans l'application, ce binding pourrait être appelé par tous les services en ayant besoin.
L'avantage étant que si le fournisseur de mail vient à changer, seulement le binding sera à mettre à jour, les services resteront inchangés.
#### Différence output binding / invocation de service
Une invocation de service est une invocation **synchrone** d'un service **interne**. Ces services peuvent être découverts par [discovery](Une invocation de service est une invocation **synchrone** d'un service **interne**). L'appel peut être sécurisé/authentifié automatiquement par l'utilisation de [Sentry](https://docs.dapr.io/concepts/dapr-services/sentry/)
-Un output binding est une invocation **sychrone ou asynchrone** d'un service **externe**. Une partie de la sécutisation des bindings sera forcément laissé au système externe.
+Un output binding est une invocation **sychrone ou asynchrone** d'un service **externe**. Une partie de la sécurisation des bindings sera forcément laissée au système externe.
{% endcollapsible %}
### En application
-> Note : La nouvelle version de l'application se trouve désormais dans `src/Lab2/3-bindings`
+> **Note** : La nouvelle version de l'application se trouve désormais dans `src/Lab2/3-bindings`
Revenons une fois encore à notre fil rouge. Cette fois-ci, deux nouvelles demandes:
- Il faut maintenant pouvoir s'interfacer avec le système d'informations du fournisseur qui réapprovisionne notre stock. Le service **stock-manager** a un endpoint HTTP POST specifique _/newproduct_
-Pour simuler ça, nous pouvons utiliser une tâche CRON. Si il est possible de l'utiliser directement dans l'application, nous pouvons utiliser un binding Dapr spécifique pour ça.
+Pour simuler ça, nous pouvons utiliser une tâche CRON. S'il est possible de l'utiliser directement dans l'application, nous pouvons utiliser un binding Dapr spécifique pour ça.
- La maison mère de l'entreprise dispose d'un service de mailing dedié. Le service **receipt-generator** doit être capable d'envoyer des mails aux clients pour confirmer les pré-commandes. Le service de mailing est disponible à l'URL suivante :
@@ -91,7 +91,7 @@ Pour simuler ça, nous pouvons utiliser une tâche CRON. Si il est possible de l
https://prod-116.westeurope.logic.azure.com/workflows/0ceb8e48b2254276923acaf348229260/triggers/manual/paths/invoke?api-version=2016-10-01&sp=%2Ftriggers%2Fmanual%2Frun&sv=1.0&sig=lTON4ZTisB1iGA-6rJAlkoC8miHB9kyJp3No
```
-Comme les deux système avec lesquels nous devons intéragir sont externes, nous choississons d'utiliser des bindings.
+Comme les deux systèmes avec lesquels nous devons intéragir sont externes, nous choississons d'utiliser des bindings.
La cible est donc la suivante :
@@ -103,7 +103,7 @@ Solution :
{%collapsible %}
Etant donné que nous voulons **réagir à un événement lancé par un système externe**, nous devons utiliser un _input binding_.
-Comme le système utilisé par le service externe est SignalR, nous pouvons utiliser le [binding CRON](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/)
+Pour simuler une tâche CRON, nous pouvons utiliser le [binding associé](https://docs.dapr.io/reference/components-reference/supported-bindings/cron/)
Le endpoint HTTP s'appelant newproduct, la propriété `metadata.name` du binding devra également s'appeller newproduct.
@@ -121,7 +121,7 @@ Comme le système utilisé par le service externe est une simple requête HTTP,
> **En pratique** : Mettez en place les deux bindings et vérifiez leur fonctionnement. Pour vérifier que le service de mailing fonctionne, vous pouvez remplir la variable d'environnement **MAIL_TO** du service **receipt-generator** avec un email valide. L'expediteur du mail sera une adresse gmail avec l'objet "Validated Command"
-**Important**: Le nom du bindsing devra être `mail`, car c'est celui qui est appelé dans le code de **receipt-generator**
+**Important**: Le nom du binding devra être `mail`, car c'est celui qui est appelé dans le code de **receipt-generator**
Une trace indiquant le succès devrait avoir cette forme :
@@ -132,7 +132,7 @@ Solution :
##### Output binding : mail
-L'output binding à utiliser pour le mail est donc un simple binding http. Il suffit donc de créer un nouveau fichier yaml dans le dossier `src/Lab2/3-bindings/component`.
+L'output binding à utiliser pour le mail est donc un simple binding http. Il suffit donc de créer un nouveau fichier yaml dans le dossier `src/Lab2/3-bindings/components`.
```yml
apiVersion: dapr.io/v1alpha1
@@ -152,7 +152,7 @@ spec:
##### Input binding : CRON
L'input binding à utiliser est un CRON.
-On crée donc encore une fois un nouveau fichier yaml dans le dossier `src/Lab2/3-bindings/component`.
+On crée donc encore une fois un nouveau fichier yaml dans le dossier `src/Lab2/3-bindings/components`.
```yml
apiVersion: dapr.io/v1alpha1
@@ -174,7 +174,6 @@ spec:
### Par curiosité: Le "système externe"
-Le système "externe" présenté est implenté comme suit:
+Le système "externe" présenté est en fait la [LogicApp](https://docs.microsoft.com/fr-fr/azure/logic-apps/logic-apps-overview) suivante:
-- Le système de mailing est une Azure FonctionApp reliée à un compte gmail, déclenchée par l'appel HTTP du dessus.
- ![Mailing](/media/lab2/bindings/logic-app-mailing.png)
+![Mailing](/media/lab2/bindings/logic-app-mailing.png)
diff --git a/instructions/_entries/03-05 monitoring.md b/instructions/_entries/03-05 monitoring.md
index bcb7801..8faad25 100644
--- a/instructions/_entries/03-05 monitoring.md
+++ b/instructions/_entries/03-05 monitoring.md
@@ -5,7 +5,7 @@ title: Observabilité
parent-id: lab-2
---
-Il est possible d'utiliser la solution Open-source Zipkin pour tracer les appels entre les services. Il suffit opour ça de configurer Dapr de la manière suivante
+Il est possible d'utiliser la solution Open-source [Zipkin](https://zipkin.io/) pour tracer les appels entre les services. Il suffit pour ça de configurer Dapr de la manière suivante
```yml
# Fichier : src/Lab2/4-observability/config/config-tracing.yml
diff --git a/instructions/_entries/04-02 create aca.md b/instructions/_entries/04-02 create aca.md
index c57608c..3c6d0e5 100644
--- a/instructions/_entries/04-02 create aca.md
+++ b/instructions/_entries/04-02 create aca.md
@@ -21,4 +21,4 @@ az group create -n --location westeurope
az containerapp env create -n -g --location westeurope
```
-Notre environnement étant crée, il ne nous reste plus que de créer les services à l'intérieur !
+Notre environnement étant crée, il ne nous reste plus qu'à créer les services à l'intérieur !