xebicon'16 : realtime react par cédric hauber, cloud designer et builder chez wescale
TRANSCRIPT
@xebiconfr #xebiconfr
CédricHauber
React Realtime @ scale
@xebiconfr #xebiconfr
1Cédric Hauber
Cloud Builder @ wescale
Scaling addictCode loverBeer drinker
@xebiconfr #xebiconfr
Le temps réel
@xebiconfr #xebiconfr
1a
- Une meilleure expérience web
Pourquoi ?
5
- Mieux capter l’attention de l’utilisateur
- Accumuler plus de données
@xebiconfr #xebiconfr
1b
- Plus qu’une fonctionnalité, un type d’application
Comment ?
6
- Pas de technologies « magiques » mais bien choisies
- Ce n’est pas si compliqué qu’il n’y paraît.
@xebiconfr #xebiconfr
2React, Redux, RethinkDB, Kubernetes… késako ?
@xebiconfr #xebiconfr
2a
- Une bibliothèque javascript- Écrit par Facebook- Des composants réutilisables- Pas de templates, une syntaxe simple (JSX) ressemblant a du
HTML- 52 000+ stars, 9 000+ forks, 800+ contributeurs
React
8
@xebiconfr #xebiconfr
2b À quoi ressemble React
9
render() { return <div> <Likes likes={this.props.likes}/> <LikeButton onIncrement={this.like}>Like</LikeButton> </div>}
@xebiconfr #xebiconfr
2c
- Une bibliothèque JavaScript- Un état global pour votre application- Permet de découpler nos composants- Permet de restituer l’était d’une application à n‘importe quel moment- Une forte communauté 24 000+ stars, 4 000+ forks, 300+
contributeurs
Redux
10
@xebiconfr #xebiconfr
2d À quoi ressemble Redux
11
export const incrementLike = (increment) => { return { type: INCREMENT_LIKES, payload: increment };};const ACTION_HANDLERS= { [INCREMENT_LIKES]: (state, action) => action.payload + state };export default function likesReducer(state = 0, action) { const handler = ACTION_HANDLERS[action.type]; return handler ? handler(state, action) : state }
@xebiconfr #xebiconfr
2e
- Une base de donnéeS NoSQL- Très bien codée- Fait pour le temps réel- JavaScript friendly- Scaling horizontal et linéaire - 16 500+ stars, 1 300+ forks et 100+ contributeurs
RethinkDB
12
@xebiconfr #xebiconfr
2f À quoi ressemble RethinkDB
13
r.table("likes").get(1).update((item) => { item.getField("value").add(1);}).run(conn)
@xebiconfr #xebiconfr
2g
- L’orchestrateur par excellence de conteneurs Docker / Rkt- Initiative lancée par Google- 17 000+ stars, 5 700+ forks et 900+ contributeurs- Pokemon Go possède le plus gros cluster Kubernetes hébergé chez
Google !
Kubernetes
14
@xebiconfr #xebiconfr
3Voyons cela en détail
@xebiconfr #xebiconfr
3a
export const rethinkMiddleware = store => next => action => { if (!action) return; if (!action.server) return next(action); if (isConnected) { sendMessage(action); } else { onConnect.push(action); }};
Redux middleware
16
@xebiconfr #xebiconfr
3b
const watchLikes = action => dispatch => { RethinkDB.execute((r, conn) => { return r.table("likes").get(1).run(conn) .then((counter) => dispatch({ type: UPDATE_LIKES_COUNT, payload: counter.value})) .then(() => { return r.table(« likes »).get(1).changes({squash: true}).run(conn)
.then((cursor) => { cursor.each((err, doc) => { if (err) return; dispatch({ type: UPDATE_LIKES_COUNT, payload: doc.new_val.value }); }); }); }); });
}; export default { [WATCH_LIKES]: watchLikes};
Server-side
17
@xebiconfr #xebiconfr
4La montée en charge
@xebiconfr #xebiconfr
4a Pourquoi Docker et Kubernetes
19
- Le meilleur moyen de packager une application
- Parce que nous voulons monter en charge rapidement
- Sans Kubernetes, orchestrer des conteneurs est un enfer.
@xebiconfr #xebiconfr
4b Notre architecture
20
RethinkDBReplicas
RethinkDBProxy
API FEED
NGINX
FRONTEND
@xebiconfr #xebiconfr
4c
Test 1 :
- 1 conteneur API- 1 conteneur FEED- 1 frontend- 500 clients / sec
Résultat :
132ms / requête0 Timeout / 0 Erreurs 500 / 0 Network errors
Résultats
21
@xebiconfr #xebiconfr
4d
Test 2:
- 10 conteneur API- 1 conteneur FEED- 1 frontend- 5000 clients / sec
Résultat :
206ms / requête0 Timeout / 0 Erreurs 500 / 0 Network errors
Résultats
22
@xebiconfr #xebiconfr
5Conclusion