Blend 2014 – Streams – Nicolas Chambrier
3/38
C'est quoi Node.js ?
●
JS côté serveur
●
Ce n'est pas maintenant qu'on rentrera dans
les détails :)
– (il faut venir au LyonJS)
Slide 4
Slide 4 text
Blend 2014 – Streams – Nicolas Chambrier
4/38
C'est quoi CloudUp ?
●
Un site en Node.js
– créé entre autres par T.J. Holowaychuck
●
Fonctionnalité principale : télécharger dès
que l'upload commence
●
C'est aussi un super prétexte pour parler de
streams
Slide 5
Slide 5 text
Blend 2014 – Streams – Nicolas Chambrier
5/38
C'est quoi les streams ?
●
Des données d'un côté
– Stockées, générées…
C'est un seau
Slide 6
Slide 6 text
Blend 2014 – Streams – Nicolas Chambrier
6/38
C'est quoi les streams ?
●
Ces données transitent
– Goutte par goutte, paquet par paquet…
– …sous forme de « flux »
C'est un tuyau
Slide 7
Slide 7 text
Blend 2014 – Streams – Nicolas Chambrier
7/38
C'est quoi les streams ?
●
On peut lire un flux (le seau)
●
On peut écrire vers un flux (le tuyau, un
autre seau…)
Slide 8
Slide 8 text
Blend 2014 – Streams – Nicolas Chambrier
8/38
C'est quoi les streams ?
●
Fluide (gaz, liquide), flux électrique, flux
d'octets (système de fichiers)…
Slide 9
Slide 9 text
Blend 2014 – Streams – Nicolas Chambrier
9/38
Et donc, les streams ?
●
Une autre façon de gérer un résultat
asynchrone :
– Asynchrone : le résultat d'une opération
– Événements : un ensemble de résultats, dans
un ordre imprévu
– Flux : un résultat éclaté en paquets arrivant
dans l'ordre
Slide 10
Slide 10 text
Blend 2014 – Streams – Nicolas Chambrier
10/38
Et donc Node.js ?
●
Module stream
●
Classes de base : Readable, …
Slide 11
Slide 11 text
Blend 2014 – Streams – Nicolas Chambrier
11/38
Et donc Node.js ?
●
Module stream
●
Classes de base : Readable, …
Slide 12
Slide 12 text
Blend 2014 – Streams – Nicolas Chambrier
12/38
Et donc Node.js ?
●
Module stream
●
Classes de base : Readable, Writable
Slide 13
Slide 13 text
Blend 2014 – Streams – Nicolas Chambrier
13/38
Et donc Node.js ?
●
Module stream
●
Classes de base : Readable, Writable
●
Brancher une readable vers une writable
Slide 14
Slide 14 text
Blend 2014 – Streams – Nicolas Chambrier
14/38
Et donc Node.js ?
●
Module stream
●
Classes de base : Readable, Writable
●
Brancher une readable vers une writable
Slide 15
Slide 15 text
Blend 2014 – Streams – Nicolas Chambrier
15/38
Et donc Node.js ?
●
Module stream
●
Classes de base : Readable, Writable
●
Implémenter ses propres streams : hériter de
Readable, Writable, Duplex, Transform…
enjoy !
– RTFM
Slide 16
Slide 16 text
Blend 2014 – Streams – Nicolas Chambrier
16/38
Et donc Node.js ?
●
Module stream
●
Classes de base : Readable, Writable
●
Créer des streams : fs, http, net…
Slide 17
Slide 17 text
Blend 2014 – Streams – Nicolas Chambrier
17/38
Attention à la gestion d'erreurs !
●
Les streams sont des EventEmitter
– Événement spécial « error »
– Crash si pas écouté
●
« pipe » NE CATCHE PAS LES ERREURS
– Écouter « error » sur TOUS les flux
– Une erreur est vite arrivée (sockets)…
Slide 18
Slide 18 text
Blend 2014 – Streams – Nicolas Chambrier
18/38
En parlant d'erreurs…
●
Que se passe-t-il si on bouche le tuyau ?
C'est un bouchon
Du coup ça va péter ?
Slide 19
Slide 19 text
Blend 2014 – Streams – Nicolas Chambrier
19/38
Ça déborde !
●
Scénarios de saturation :
– Des données prête dans une readable, qui
s'accumulent car personne ne lit
Accumulation de données
(readable)
Slide 20
Slide 20 text
Blend 2014 – Streams – Nicolas Chambrier
20/38
Ça déborde !
●
Scénarios de saturation :
– Des données prête dans une readable, qui
s'accumulent car personne ne lit
●
Buffering (Google: « Streams under the hood »)
●
highWaterMark
Accumulation de données
(readable)
Slide 21
Slide 21 text
Blend 2014 – Streams – Nicolas Chambrier
21/38
Ça déborde !
●
Scénarios de saturation :
– Le writable n'est pas prêt mais on insiste pour lui
balancer des données
On essaie d'écrire mais
on pousse sur le bouchon
(writable)
Slide 22
Slide 22 text
Blend 2014 – Streams – Nicolas Chambrier
22/38
Ça déborde !
●
Scénarios de saturation :
– Le writable n'est pas prêt mais on insiste pour lui
balancer des données
●
Retour booléan de « write() »
●
Événement « drain »
On essaie d'écrire mais
on pousse sur le bouchon
(writable)
Slide 23
Slide 23 text
Blend 2014 – Streams – Nicolas Chambrier
23/38
Ça déborde !
●
Ces règles sont facultatives
– Les implémentations ne tiennent pas forcément
compte de « highWaterMark »
– L'utilisateur est libre de ne pas tenir compte du
retour de « write() »
Slide 24
Slide 24 text
Blend 2014 – Streams – Nicolas Chambrier
24/38
Ça déborde !
●
Ces règles sont facultatives
– Les implémentations ne tiennent pas forcément
compte de « highWaterMark »
– L'utilisateur est libre de ne pas tenir compte du
retour de « write() »
– Assumez les conséquences
Et ça c'est ta RAM
Slide 25
Slide 25 text
Blend 2014 – Streams – Nicolas Chambrier
25/38
Ça déborde !
●
fs.createReadStream respecte le
highWaterMark
Slide 26
Slide 26 text
Blend 2014 – Streams – Nicolas Chambrier
26/38
OK c'est cool !
●
Un « chunk » on ne peut pas en faire grand-
chose
– Exception : « objectMode » mais on n'a pas trop
le temps là
●
La plupart du temps on doit attendre la fin
du flux pour commencer à en faire quelque-
chose
– Doin it wrong
Slide 27
Slide 27 text
Blend 2014 – Streams – Nicolas Chambrier
27/38
Ah c'est pas cool en fait ?
●
C'est pour traiter des flux d'information
– Use-case : upload
●
OK mais l'upload je sais déjà gérer…
Slide 28
Slide 28 text
Blend 2014 – Streams – Nicolas Chambrier
28/38
Ah c'est pas cool en fait ?
●
C'est pour traiter des flux d'information
– Use-case : upload
●
OK mais l'upload je sais déjà gérer…
●
Et stocker le fichier à deux endroits en même
temps, à mesure qu'il s'uploade, tu sais
faire ?
Slide 29
Slide 29 text
Blend 2014 – Streams – Nicolas Chambrier
29/38
Ah c'est pas cool en fait ?
●
C'est pour traiter des flux d'information
– Use-case : upload
●
OK mais l'upload je sais déjà gérer…
●
Et lancer un download au fur et à mesure
que ça upload ?
Slide 30
Slide 30 text
Blend 2014 – Streams – Nicolas Chambrier
30/38
Ah c'est pas cool en fait ?
●
C'est pour traiter des flux d'information
– Use-case : upload
●
OK mais l'upload je sais déjà gérer…
●
Et lancer un download au fur et à mesure
que ça upload ?
●
Il y en a qui montent des startups avec ça !
Slide 31
Slide 31 text
Blend 2014 – Streams – Nicolas Chambrier
31/38
Implémentation
●
Implémentation naïve :
– Garder la request de l'utilisateur 1 en mémoire
– « pipe » vers la response de l'utilisateur 2
●
Problèmes :
– Plusieurs uploads ?
Slide 32
Slide 32 text
Blend 2014 – Streams – Nicolas Chambrier
32/38
Implémentation
●
Implémentation naïve :
– Garder la request de l'utilisateur 1 en mémoire
– « pipe » vers la response de l'utilisateur 2
●
Problèmes :
– Plusieurs uploads ?
●
Un hashmap des requests en mémoire
Slide 33
Slide 33 text
Blend 2014 – Streams – Nicolas Chambrier
33/38
Implémentation
●
Implémentation naïve :
– Garder la request de l'utilisateur 1 en mémoire
– « pipe » vers la response de l'utilisateur 2
●
Problèmes :
– Plusieurs uploads ?
– Plusieurs downloads d'un même upload ?
Slide 34
Slide 34 text
Blend 2014 – Streams – Nicolas Chambrier
34/38
Implémentation
●
Implémentation naïve :
– Garder la request de l'utilisateur 1 en mémoire
– « pipe » vers la response de l'utilisateur 2
●
Problèmes :
– Plusieurs uploads ?
– Plusieurs downloads d'un même upload ?
●
Ce qui est déjà téléchargé a été lu depuis la request,et
ne peut être re-lu
●
Stocker ce qui a déjà été lu, faire un système de
reprise…
Slide 35
Slide 35 text
Blend 2014 – Streams – Nicolas Chambrier
35/38
Implémentation
●
Implémentation naïve :
– Garder la request de l'utilisateur 1 en mémoire
– « pipe » vers la response de l'utilisateur 2
●
Problèmes :
– Plusieurs uploads ?
– Plusieurs downloads d'un même upload ?
– L'occupation mémoire ?
Slide 36
Slide 36 text
Blend 2014 – Streams – Nicolas Chambrier
36/38
Implémentation
●
Implémentation naïve :
– Garder la request de l'utilisateur 1 en mémoire
– « pipe » vers la response de l'utilisateur 2
●
Implémentation un peu plus maline :
– Module « pending-streams »
Slide 37
Slide 37 text
Blend 2014 – Streams – Nicolas Chambrier
37/38
Implémentation
●
Implémentation naïve :
– Garder la request de l'utilisateur 1 en mémoire
– « pipe » vers la response de l'utilisateur 2
●
Implémentation un peu plus maline :
– Module « pending-streams »