Upload
xebia-france
View
190
Download
3
Embed Size (px)
Citation preview
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Trois heures à l’assaut d’une application réactive
Xavier Bucchiotty Nicolas Jozwiak Vincent Spiewak
@njozwiak @xbucchiotty @vspiewak#3ReactApp
@vspiewak
Speakers
@xbucchiotty
http://blog.xebia.fr
@njozwiak
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Agenda Contexte
Comment concevoir ?
Comment développer ?
Comment déployer ?
Comment monitorer ?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Agenda Contexte
Comment concevoir ?
Comment développer ?
Comment déployer ?
Comment monitorer ?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture monolithique
Device Gateway Reporting Alerting Front WEB
Provider A
12
3 4
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture monolithique
Device Gateway Reporting Alerting Front WEB
Provider A
12
3 4
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Agenda Contexte
Comment concevoir ?
Comment développer ?
Comment déployer ?
Comment monitorer ?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture monolithique
Device Gateway Reporting Alerting Front WEB
Provider A
12
3 4
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Reporting Alerting Front WEB
Provider A
12
3 4
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
12
Reporting
Alerting3
configuration
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
12
Reporting
Alerting
3
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
12
Reporting
Alerting
3
Circuit breaker
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Microservices
Microservice
Business DomainIsoler les problèmes
Déploiements indépendants
Loi de Conway
Cacher les détails d’implémentation
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
2
Reporting
AlertingCircuit breaker
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
2
Reporting
AlertingCircuit breaker
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
2
Reporting
AlertingCircuit breaker
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
2
Reporting
AlertingCircuit breaker
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Contexte transactionnel
Provider B
Device
Provider A
Gateway
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Contexte transactionnelContexte transactionnel
Reporting
Alerting
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
CQRS
Provider B
Device
Provider A
Gateway
query
Front WEB
API command
API
API
Reporting
Alerting
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Dynamique du système
Provider B
Device Front WEB
Provider A
API
API
API
Gateway
Reporting
Alerting
DATAFLOW
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Reactive Manifesto
Message driven
Elastic Resilient
Responsive
www.reactivemanifesto.org
@njozwiak @xbucchiotty @vspiewak#3ReactApp
//asynchrone def handle(event): Result = { val f1 = Future(report(event)) val f2 = Future(alert(event))) Await.result(sequence(f1,f2)) Success }
// asynchrone et non bloquant :) def handle(event): Future[Result] = { val f1 = Future(report(event)) val f2 = Future(alert(event))) sequence(f1, f2).map(_ => Success) }
Asynchronisme
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Architecture
Device Gateway Front WEB
Provider A
2
Reporting
AlertingCircuit breaker
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Agenda Contexte
Comment concevoir ?
Comment développer ?
Comment déployer ?
Comment monitorer ?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Framework asynchrone JVM
La programmation concurrente est difficile.
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Framework asynchrone JVM
La programmation concurrente est difficile.
Callbacks?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Framework asynchrone JVM
La programmation concurrente est difficile.
ExecutorService?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Framework asynchrone JVM
La programmation concurrente est difficile.
Modèle acteur
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Modèle acteur
acteur
la boîte aux lettres seul élément public d’un acteur
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Modèle acteur
réponse
acteur acteur acteur
requête transfert
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Modèle acteur
A B
D I S P A T C H E R
THREADS
B
A
C D
D
CA
t
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Développer en local avec les contraintes du distribué
Framework asynchrone JVM
@njozwiak @xbucchiotty @vspiewak#3ReactApp
akka-clusterakka.actor.deployment { /orchestration { router = round-robin-group nr-of-instances = 100 routees.paths = ["/user/orchestration"] cluster { enabled = on allow-local-routees = off use-role = orchestration } } }
@njozwiak @xbucchiotty @vspiewak#3ReactApp
akka-cluster est la clé de l’élasticité et de la résilience du système.
akka-cluster
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Reactive Manifesto et Akka
Message driven
Elastic Resilient
Responsive
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Technos
Device Front WEB
Provider A
API
API
API
GatewayCircuit
breaker
Reporting
Alerting
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Journal distribué
Développé à l’origine chez LinkedIn
Rapide, robuste, scalable
File d’attentes, agrégation logs, streaming
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Journal distribué
TOPIC
BROKER 1
ZK
0
1
leader
BROKER 2
synchro
@njozwiak @xbucchiotty @vspiewak#3ReactApp
TOPIC
Journal distribué
BROKER 1
ZK
0
1
leader
BROKER 2
leader
replicasynchro
@njozwiak @xbucchiotty @vspiewak#3ReactApp
TOPIC
Journal distribué
ZK
0
1
leader
BROKER 2
leader
replicasynchro
@njozwiak @xbucchiotty @vspiewak#3ReactApp
TOPIC
Journal distribué
ZK
0
1
BROKER 2
leader
synchro
Élasticité
Résilience
@njozwiak @xbucchiotty @vspiewak#3ReactApp
TOPIC
Journal distribué
BROKER 1
ZK
0
1
leader
BROKER 2
leader
replicaproducer
message pour partition 0
@njozwiak @xbucchiotty @vspiewak#3ReactApp
TOPIC
Journal distribué
BROKER 1
ZK
0
1
leader
BROKER 2
leader
replicaproducer
message pour partition 1
@njozwiak @xbucchiotty @vspiewak#3ReactApp
TOPIC
Journal distribué
BROKER 1
ZK
0
1
leader
BROKER 2
leader
replicaproducer
message pour partition 1
ordre garanti au sein d’une partition
@njozwiak @xbucchiotty @vspiewak#3ReactApp
TOPIC
Journal distribué
BROKER 1
ZK
0
1
leader
BROKER 2
leaderconsumer 1topic T
partition 0group A
ordre garanti au sein d’une partition
consumer 2
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Kafka topic
0 1 2 3 4 5 6 7 8 9
Nouveaux messages
Anciens messages
offset
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Kafka topic
0 1 2 3 4 5 6 7 8 9
Nouveaux messages
Anciens messages
Consommateur groupe G1
Consommateur groupe G2
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Reactive Manifesto et Kafka
Message driven
Elastic Resilient
Responsive
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Technos
Device Front WEB
Provider A
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Document
{ "device" : "device1234" "msg" : "some message" "timestamp" : "2015-04-08T13:30:00.000Z" }
Event
ESevents-2015
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Elastique - Shards
Node 1INDEX
0
1'
2
Node 2INDEX
0'
1
2'
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Elastique - Shards
Node 1INDEX
0
1'
2''
Node 2INDEX
0'
1''
2
Node 3INDEX
0''
1
2'
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Node 3Node 2
Elastique - Noeuds
Node 1master
Node 3Node 2
Node 1data
Node 3Node 2
Node 1search
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Résilient - Shards
Node 1INDEX
0
1'
2''
Node 2INDEX
0'
1''
2
Node 3INDEX
0''
1
2'
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Résilient - Shards
Node 1INDEX
0
1'
2
Node 2INDEX
0'
1
2'
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Bounded QueuesNode
Queue (index)
Queue (bulk)
Queue (get)
Queue (refresh)
Queue (search)
…
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Responsive - Timeout
Node 1
http://node1:9200/_search?timeout=10000
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Recherche
Node 1TWITTER
0 1'
Node 2EVENT
0' 1
Node 3EVENT
0'' 1''
12
3’ 3’’
4
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Reactive Manifesto et ES
Message driven
Elastic Resilient
Responsive
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Technos
Device Front WEB
Provider A
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Couchbase
Gestion documents
Schemaless
Clé / valeur
Cache distribué
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Reactive Manifesto et CB
Message driven
Elastic Resilient
Responsive
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Technos
Device Front WEB
Provider A
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
PLAY
Formulaires, Json, validation
Intégration Scala et Akka
IO non bloquant
Sans état
@njozwiak @xbucchiotty @vspiewak#3ReactApp
REACT JS
Créé par Facebook et Instagram
Composants
Data flow unique
Performant
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Reactive Manifesto et Play
Message driven
Elastic Resilient
Responsive
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Technos
Device Front WEB
Provider A
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Testing
Gateway
Endpoint Supervision
WorkersRouter
Provider B
Device
Provider A
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Gateway
Test unitaire
Endpoint Supervision
WorkersRouter
Provider B
Device
Provider A
testkit
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Gateway
Test unitaire
Endpoint Probe
WorkersProbe
Probe testkit
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Test unitairedescribe("A kafka source actor") { it("should be able to pump a given number of message from kafka") { val probe = TestProbe() val reader = system.actorOf(Props(classOf[KafkaSource], probe)) //send 11 messages on a topic probe.send(reader, 10) probe.receiveN(10, max = 3.seconds) shouldBe messages.take(10) probe.expectNoMsg(1.second) } }
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Test unitairedescribe("A terminal session") { it("should have an idle timeout") { implicit val system = ActorSystem("test", ConfigFactory.parseString("session.timeout=\"500 milliseconds\"")) val probe = TestProbe() val session = system.actorOf(DeviceSession.props) probe.watch(session) probe.expectTerminated(session, 1.second) } }
@njozwiak @xbucchiotty @vspiewak#3ReactApp
"form a cluster" in { runOn(clusterNodes: _*) { SeedDiscovery.joinCluster(system) enterBarrier("deployed")
}
"support network partition" in { runOn(node1) { for { from <- group_1 to <- group_2 } { testConductor.blackhole(from, to, Direction.Both).await } }
Test multi-jvm
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Résumé
Device Front WEB
Provider A
Reporting
Alerting
API
API
API
GatewayCircuit
breaker
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Agenda Contexte
Comment concevoir ?
Comment développer ?
Comment déployer ?
Comment monitorer ?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
DockerFROM ubuntuRUN apt-get install -y wget software-properties-commonRUN apt-add-repository ppa:ansible/ansibleRUN apt-get update && apt-get install -y ansibleRUN wget https://bootstrap.pypa.io/ez_setup.py -O - | pythonRUN easy_install pipRUN pip install botoENV ANSIBLE_HOST_KEY_CHECKING=False
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Technos
Device Front WEB
Provider A
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Marathon
Execution d’applications
API Rest
Beaucoup d’options
@njozwiak @xbucchiotty @vspiewak#3ReactApp
{ "id": "provisioning", "instances": 1, "cpus": 2.0, "mem": 512, "ports":[9000], "container": { "type": "DOCKER", "docker": { "image": "project/web:0crec10a90724f791caaf95cbc62ea61abbd6376", "network": "BRIDGE", "portMappings": [ { "containerPort": 9000, "servicePort": 9000, "hostPort": 0, "protocol": "tcp" } ] } } }
Marathon Config
@njozwiak @xbucchiotty @vspiewak#3ReactApp
… "healthChecks": [ { "path":"/health", "portIndex":0, "protocol":"HTTP", "gracePeriodSeconds":3, "intervalSeconds":10, "timeoutSeconds":10, "maxConsecutiveFailures":3 } ], … "upgradeStrategy": { "minimumHealthCapacity": 0 }, …
Marathon Config
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Architecture
Mesos master
Gateway Reporting
Alerting
Mesos slave / Marathon
Gateway
Alerting Reporting
Web
Http Post
Mesos slave / Marathon
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Découverte de services
seed-nodes 1 seed-nodes 1
seed-nodes 2
Nodes 1
Nodes 2
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Découverte de services• Akka 2.4 snapshot
• Intégration avec Docker
remote { enabled-transports = ["akka.remote.netty.tcp"] netty.tcp { hostname = "127.0.0.1" port = 2551 } }
remote { enabled-transports = ["akka.remote.netty.tcp"] netty.tcp { hostname = "127.0.0.1" port = 2551 bind-hostname = "192.132.122.12" bind-port = 32001 } }
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Node 1
Node 2
Découverte de services
joinCluster
joinCluster
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Problème IP dynamique
Port dynamique
Nombre d’instances
Sous domaines (web, monitoring, …)
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Bamboo
Cluster Mesos
Cluster Marathon
Bamboo Zookeeper HAProxy
API /v2/eventSubscriptions
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Bamboo
Cluster Mesos
Cluster Marathon
Bamboo
Bamboo HAProxy
WEB 1
Zookeeper
WEBChronos Inbound
WEB 2 WEB N
Docker Registry
web.app.io
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Problème Kafka
Couchbase
Marathon
Mesos master / slave
Elasticsearch master / search / data
GoCD server / agent
…
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Introduction Infrastructure as code
Agent-less
Python / Boto
@njozwiak @xbucchiotty @vspiewak#3ReactApp
$ cat inventory [webservers] foo.example.com bar.example.com
[dbservers] one.example.com two.example.com
Inventaire
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Modules Commands (command, shell, script)
Files (file, copy, unarchive, …)
System (service, hostname, cron, …)
Packaging (apt, yum, …)
Source Control (git, svn, …)
Notifications (mail, irc, slack, …)
@njozwiak @xbucchiotty @vspiewak#3ReactApp
$ cat tasks/main.yml - name: Create /mnt/data directory file: path=/mnt/data/elasticsearch state=directory
- name: Install Elasticsearch apt: name=elasticsearch state=latest force=yes notify: Restart Elasticsearch
Tasks
@njozwiak @xbucchiotty @vspiewak#3ReactApp
$ tree -a . ├── files │ └── template.json ├── handlers │ └── main.yml ├── tasks │ └── main.yml ├── templates │ └── elasticsearch.conf.j2 └── vars └── .gitkeep
Rôles
@njozwiak @xbucchiotty @vspiewak#3ReactApp
$ cat group_vars/elasticsearch
elasticsearch: version: 1.4 clustername: elasticsearch-cluster nodename: {{ hostvars[inventory_hostname]['ec2_id'] }} quorom: 1 replicas: 2 plugins: - head - paramedic
Variables
@njozwiak @xbucchiotty @vspiewak#3ReactApp
discovery.zen.ping.multicast.enabled: false discovery.zen.ping.unicast.hosts: [ {% for host in groups[group_name] %}
"{{ hostvars[host]['ansible_eth0'].ipv4.address }}"
{% if not loop.last %},{% endif %}
{% endfor %} ]
Templates
@njozwiak @xbucchiotty @vspiewak#3ReactApp
$ cat elasticsearch.yml - hosts: es_nodes user: ubuntu sudo: yes
roles: - all - java - elasticsearch
Playbooks
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Résultats Création instances EC2
Configuration DNS (Route 53)
Configuration instances
Ré-utilisation des rôles (all, java, zk, …)
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Technos
Device Front WEB
Provider A
API
API
API
@njozwiak @xbucchiotty @vspiewak#3ReactApp
VPC + CROSS AZ
VPCAZ1 AZ2
PUBLIC
PRIV
PUBLIC
PRIV
WEBWEB GWGW
@njozwiak @xbucchiotty @vspiewak#3ReactApp
GO CD: Principes
GO Server
GO Agent GO Agent GO Agent
DEV PROD
@njozwiak @xbucchiotty @vspiewak#3ReactApp
GO CD: Principes
Update ES
Update Kafka
Create Infra
pipeline
stage
jobs
jobs…
@njozwiak @xbucchiotty @vspiewak#3ReactApp
GO CD: Principes
Create Infra Update Infra
Pipeline Group
Pipeline
Docker Images Deploy Containers
Pipeline Pipeline Pipeline
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Déploiement continu
Build source + run tests
docker build img
docker push img
install img instanceHttp Post to Marathon
docker run img
slave masterHub
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Http post to Marathon
publish
Build Marathon request with dynamic parameters
@njozwiak @xbucchiotty @vspiewak#3ReactApp
SBTcpu in Marathon := 2 memory in Marathon := 512 instances in Marathon := 1 portsMapping in Marathon := Seq(dynamicPort(9000, Protocol.TCP))
healthchecks in Marathon := Seq(httpHealthCheck("/health", 3, 10, 10, 3))
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Kafka
TOPIC
0
1 Reporting
Reporting
2 partitions deploy 2 instances
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Agenda Contexte
Comment concevoir ?
Comment développer ?
Comment déployer ?
Comment monitorer ?
@njozwiak @xbucchiotty @vspiewak#3ReactApp
KPI
Provider B
Device
Provider A
GatewayCircuit
breaker
UP TIME
LATENCE
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Bilan A/B testing
Schemaless
Facile à exploiter
En cours de réflexion, développement
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Provider B
Améliorations
Device
Provider A
API
APIGateway Front
WEB
Reporting
Alerting
API
stream
stream
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Prise de recul
Déploiements
Mise en place de tests
Granularité des services
Culture du client
@njozwiak @xbucchiotty @vspiewak#3ReactApp
Bibliographie
http://www.se-radio.net/2014/10/episode-213-james-lewis-on-microservices/
Standing on the shoulders of giants