Skip to content

Blogs de Développeurs: Aggrégateur de Blogs d'Informatique sur .NET, Java, PHP, Ruby, Agile, Gestion de Projet

Forum Logiciel

Forum Logiciel : diffusion de connaissance et d’informations sur toutes les activités liées au développement d’applications informatiques en entreprise.

Agrégateur de flux

Nous accueillons le 28 janvier, le Paris MongoDB User Group !

global_430204062Le 28 janvier prochain, venez assistez au premier meetup du WParis MongoDB User Group de l’annĂ©e !

Au programme :

 

Meteor par Vianney Lecroart

Après une courte introduction sur ce qu’est Meteor (10mn), Vianney live codera une application de A (dossier vide) Ă  Z (application dĂ©ployĂ©) en Meteor afin de vous donner un appercu de ce qu’on peut faire avec.

Vianney est l’ambassadeur Meteor en France et dĂ©veloppe en Meteor depuis plus de 2 ans. Il est Hacker in residence dans le Startup Studio eFounders.

Keljob par Nouhoum Traoré

Nous avons utilisé Play/Scala/Akka/Reactivemongo pour moderniser une application web monolithique et partiellement endetté. Dans ce talk je vous présenterai ce que nous avons appris dans ce parcours. Nous parlerons du refactoring de l’architecture existante, de la migration des données de SQL vers Mongo DB et du développement d’une API REST avec Play. Nous aborderons également les tests avec Play et MongoDB.

Informations pratiques

Vous pouvez vous inscrire ici : http://www.meetup.com/Paris-MongoDB-User-Group/events/219345923/

Rendez-vous dès 19h15 au 156 boulevard Haussmann, 7ème étage.

Nous vous offrons un buffet campagnard.

A mercredi prochain !

Catégories: Blog Société

Grunt (3) : Configurer les tâches

Avec le prĂ©cĂ©dent article sur l’API Grunt, vous avez eu un aperçu de comment accĂ©der Ă  la configuration et aux fichiers. Dans cet article, vous allez mettre en pratique ces connaissances dans le cadre de la configuration des tâches. A...
Catégories: Blog Société

Introduction Ă  Terraform

LancĂ© en juillet dernier, l’outil d’infra as code Terraform offre dĂ©sormais un niveau de fonctionnalitĂ© permettant la configuration d’une infrastructure cloud complète.

Voyons dans le cadre de l’architecture d’une plateforme web comment crĂ©er une plateforme complète sur Amazon en utilisant Terraform.

Terraform est un outil open source d’infrastructure as code, Ă©crit en go, dont l’approche est d’autoriser la dĂ©finition d’une architecture aussi hĂ©tĂ©rogène que possible et ainsi faire cohabiter des instances Amazon EC2 et Google Cloud Engine, gĂ©rer son DNS avec DNSimple ou encore envoyer les mailings avec Mailgun. Sur la page d’introduction du projet, Terraform se compare avec d’autres solutions du marchĂ©, assumant pleinement ne pas remplir les mĂŞmes fonctions que Puppet ou Chef. Le duel avec Ansible est malheureusement absent. Saluons cependant la dĂ©marche.

Si les dĂ©veloppements se sont jusqu’Ă  prĂ©sent principalement focalisĂ©s sur les services Amazon, d’autres providers sont supportĂ©s officiellement et la liste augmente au fil des versions. Il est possible de crĂ©er son propre module et les initiatives pour ajouter les providers d’autres solutions Ă©mergent de la communautĂ© (Openstack, VMware, …)

Intégration avec le monde extérieur

L’ensemble d’un projet Terraform s’organise autour de fichiers de configuration, lesquels sont de simples fichiers texte qui peuvent ĂŞtre Ă©crits au format spĂ©cifique de Terraform (.tf) ou en JSON (.tf.json). Si le premier est prĂ©fĂ©rable, autorisant les commentaires et utilisant une syntaxe plus concise, le second offre la flexibilitĂ© de JSON, interprĂ©table par la grande majoritĂ© des langages.

Il est possible d’exporter toutes les valeurs de son infrastructure dans des fichiers texte en utilsant la commande output. Nous pouvons donc, par exemple gĂ©nĂ©rer un fichier d’inventaire pour une utilisation ultĂ©rieure.

Lors de la crĂ©ation de l’infrastructure, Terraform gĂ©nère un fichier d’Ă©tat (terraform.tfstate). Depuis la version 0.3, ce fichier est au format JSON, lisible humainement Ă  des fins de debug mais plus certainement pour s’interfacer avec d’autres outils. Notons dans cette veine le projet terraform-inventory qui transforme un Ă©tat terraform, en fichier utilisable par Ansible. En pratique, parcourir le fichier d’Ă©tat est suffisamment simple pour se permettre de crĂ©er son propre parser. Voici un exemple de parser Ă©crit en javascript.

Terraformons par l’exemple Architecture d’une plateforme web

Prenons le cas simple d’une architecture web dans laquelle le service est accessible via un loadbalancer (lb) qui rĂ©partit la charge sur plusieurs serveurs hĂ©bergeant l’application (web), lesquels communiquent avec une base de donnĂ©es (db). Cette plateforme sera intĂ©gralement hĂ©bergĂ©e sur AWS.

Les diffĂ©rents fichiers d’un projet Terraform

Tous les fichiers sont regroupĂ©s dans un mĂŞme rĂ©pertoire, Ă  l’heure actuelle il n’est pas possible d’organiser son projet en sous-dossier. Sachez cependant qu’il est possible d’organiser un projet en modules, lesquels peuvent ĂŞtre hĂ©bergĂ©s localement ou sur un dĂ©pĂ´t git distant.

├── database.tf
├── loadbalancer.tf
├── main.tf
├── terraform.tfstate
├── terraform.tfstate.backup
├── terraform.tfvars
├── variables.tf
└── webserver.tf

 

  • *.tf : les fichiers d’extension tf dĂ©finissent l’infrastructure Ă  gĂ©nĂ©rer. La configuration dans son ensemble peut ĂŞtre rĂ©partie dans plusieurs fichiers. Ces derniers seront alors lus par ordre alphabĂ©tique et analysĂ©s avant d’ĂŞtre appliquĂ©s, nous Ă©conomisant ainsi la gestion des dĂ©pendances entre les Ă©lĂ©ments.
  • terraform.tfstate : fichier d’Ă©tat de l’infrastructure. Il est gĂ©nĂ©rĂ© lors de l’application des fichiers et est indispensable au bon fonctionnement de l’application. Des informations sensibles y sont prĂ©sentes, il faut donc Ă©viter de l’intĂ©grer au gestionnaire de source.
  • terraform.tfstate.backup : version n-1 du fichier tsfate
  • terraform.tfvars : fichier de configuration. Si aucun fichier de configuration n’est spĂ©cifiĂ©, terraforn recherche alors terraform.tfvars. Ce fichier peut contenir les identifiants aux diffĂ©rents providers, auquel cas il ne devrait pas ĂŞtre enregistrĂ© dans le gestionnaire de source. Il est conseillĂ© d’utiliser un autre fichier pour les valeurs non sensibles, variables.tf par exemple.
Les variables

Les variables sont dĂ©clarĂ©es par l’instruction variable, et peuvent prendre une valeur par dĂ©faut et une description

variable "access_key" {}
variable "secret_key" {}
variable "key_name" {}
variable "key_path" {}
variable "www_count" {
  description = "Number of web servers"
  default = "2"
}
variable "aws_region" {
  default = "eu-west-1"
}

# Using ubuntu amis
variable "aws_amis" {
  default = {
    eu-west-1 = "ami-b1cf19c6"
    us-east-1 = "ami-de7ab6b6"
    us-west-1 = "ami-3f75767a"
    us-west-2 = "ami-21f78e11"
  }
}
variable "project" {
  default = "tf-demo"
}

Il est ensuite possible de définir leur valeurs dans le fichier de configuration par défaut terraform.tfvars ou en précisant le fichier à utiliser en ligne de commande avec le paramètre -var-file. Notons ici la définition des credentials Amazon access_key et secret_key

access_key = "your_access_key"
secret_key = "your_secret_key"
key_name = "keyname"
key_path = "/path/to/the/private-key.pem"

Il est Ă©galement possible de dĂ©finir la valeur des variables Ă  l’Ă©xĂ©cution avec le paramètre -var.

L’utilisation d’une variable NOM_VARIABLE se fait directement par ${var.NOM_VARIABLE}.

# AWS provider
provider "aws" {
    access_key = "${var.access_key}"
    secret_key = "${var.secret_key}"
    region = "${var.aws_region}"
}
# Security group
resource "aws_security_group" "default" {
    name = "tf-demo-sg"
    description = "Allow ssh and web access"
    # SSH access from anywhere
    ingress {
      from_port = 22
      to_port = 22
      protocol = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
    # HTTP access from anywhere
    ingress {
      from_port = 80
      to_port = 80
      protocol = "tcp"
      cidr_blocks = ["0.0.0.0/0"]
    }
}
# DNS
resource "aws_route53_zone" "primary" {
   name = "tfdemo.com"
}

Le provider AWS a besoin d’ĂŞtre configurĂ© avec les identifiants et la rĂ©gion. Cette configuration Ă©tant globale, il n’est pas possible, Ă  ce jour, de configurer plusieurs providers du mĂŞme type et donc d’utiliser diffĂ©rentes rĂ©gions en parallèle.

La configuration d’un security group requiert les attributs name et description. Chaque règle de sĂ©curitĂ© est dĂ©finie par les attributs ingress, lesquels peuvent ĂŞtre rĂ©pĂ©tĂ©s autant que souhaitĂ©.

Le provider AWS fournit les ressources nĂ©cessaire Ă  la gestion des DNS en utilisant route53. DĂ©clarons dans un premier temps la zone de notre exemple qui sera rĂ©fĂ©rencĂ©e par d’autres ressources.

Server web
resource "aws_instance" "www" { 
  key_name = "${var.key_name}"
  ami = "${lookup(var.aws_amis, var.aws_region)}"
  instance_type = "t1.micro"
  count = "${var.www_count}"
  tags {
    Name = "tfdemo-www-${count.index}"
    Project = "tf-demo"
  }
  
  security_groups = ["${aws_security_group.default.name}"]

 connection {
    # The default username for our AMI
    user = "ubuntu"
    # The path to your keyfile
    key_file = "${var.key_path}"
  }

  provisioner "remote-exec" {
    inline = [
    "sudo apt-get -y update",
    "sudo apt-get -y install nginx",
    "sudo service nginx start"
    ]
  }
}

resource "aws_route53_record" "tf-demo-www-record" {
  name = "${concat("www", count.index,".", aws_route53_zone.primary.name)}"
  count = "${var.www_count}"
  zone_id = "${aws_route53_zone.primary.zone_id}"
  type = "A"
  records = ["${element(aws_instance.www.*.public_ip, count.index)}"]
  ttl = "1"
}

Examinons les instructions utilisées :

resource "aws_instance" "www"

Nous demandons la crĂ©ation d’une instance amazon nommĂ©e "www". Le nommage des ressources respecte la format <PROVIDER>_<RESOURCE>, aws_instance est donc une resource de type instance du provider aws. Le nom de la ressource est arbitraire et servira d’identifiant pour tout autre ressource y faisant rĂ©fĂ©rence.

key_name = "${var.key_name}"

La paramètre key_name dĂ©fini la clĂ© ssh Ă  importer dans l’instance. La valeur est rĂ©cupĂ©rĂ©e depuis la variable Ă©galement nommĂ©e key_name par simplicitĂ©. Notons que la variable est remplacĂ©e avant interpretation, les guillemets doubles sont donc ici nĂ©cessaires dans la mesure oĂą key_name est une chaĂ®ne de caractère.

ami = "${lookup(var.aws_amis, var.aws_region)}"

Le paramètre ami reprĂ©sente l’id de l’AMI qui sera utilisĂ©. Introduisons la fonction lookup qui rĂ©cupère une valeur Ă  partir de sa clĂ© dans un dictionnaire. La valeur de l’AMI Ă  utiliser est ici lue depuis la variable dictionnaire aws_amis Ă  partir de la variable aws_region.

count = "${var.www_count}"

Certaines ressources acceptent un paramètre count qui renseigne le nombre d’instances Ă  dĂ©marrer.

tags {
    Name = "tfdemo-www-${count.index}"
    Project = "tf-demo"
  }

Les tags ont rĂ©ellement manquĂ© dans les premières versions de terraform. Ils ont la mĂŞme signification que les tags dans Amazon. Il est ainsi aisĂ© de nommer son instance en utilisant le tag "Name" dont le nom est conventionnel, il est Ă©galement possible de dĂ©finir librement d’autres tags, tel qu’un tag "Projet" par exemple.

connection {
    # The default username for our AMI
    user = "ubuntu"
    # The path to your keyfile
    key_file = "${var.key_path}"
  }

L’instruction connection dĂ©finit comment se connecter en ssh Ă  l’instance. Ici, la connexion se fait via l’utilisateur par dĂ©faut ubuntu en utilisant la clĂ© ssh spĂ©cifiĂ©e par keyname

 security_groups = ["${aws_security_group.default.name}"]

security_groups dĂ©finit la liste des "security groups" Amazon. ${aws_security_group.default.name} fait rĂ©fĂ©rence Ă  une ressource aws_security_group dĂ©finie dans un autre fichier. Terraform se chargeant pour nous de rĂ©soudre les dĂ©pendances entre les ressources, nous n’avons pas Ă  nous soucier de l’endroit oĂą il est dĂ©fini.

provisioner "remote-exec" {
    inline = [
    "sudo apt-get -y update",
    "sudo apt-get -y install nginx",
    "sudo service nginx start"
    ]
  }

Terraform aborde la notion de provisionning mĂŞme si cela se cantonne aujourd’hui au transfert de fichier et l’exĂ©cution de commandes locales ou distantes. Cependant cela suffit Ă  appeler des outils de provisionning tels que Chef, Puppet ou Ansible lesquels pourront prendre la main en utilisant les donnĂ©es exportĂ©es. Le provisionner remote-exec utilise la connection dĂ©clarĂ©e dans la mĂŞme instance pour installer et dĂ©marrer nginx.

resource "aws_route53_record" "tf-demo-www-record" {
  name = "${concat("www", count.index,".", aws_route53_zone.primary.name)}"
  count = "${var.www_count}"
  zone_id = "${aws_route53_zone.primary.zone_id}"
  type = "A"
  records = ["${element(aws_instance.www.*.public_ip, count.index)}"]
  ttl = "1"
}

Pour chaque instance "www", nous associons une entrĂ©e DNS dans la zone "primary". La fonction concat permet de crĂ©er simplement une nomenclature, la première instance aura ainsi le nom de domaine "www0.tfdemo.com". La version 0.3.5 introduit la fonction element qui retourne le Nième Ă©lĂ©ment d’une liste. Le nom de domaine fraichement crĂ©Ă© sera alors affectĂ© Ă  l’ip public de l’instance par un champ de type A.

Base de données
resource "aws_instance" "db" {
  key_name = "${var.key_name}"
  ami = "${lookup(var.aws_amis, var.aws_region)}"
  instance_type = "t1.micro"
  tags {
    Name = "tf-demo-db"
    Project = "${var.project}"
  }
  security_groups = ["${aws_security_group.default.name}"]
}

resource "aws_route53_record" "tf-demo-db-record" {
  name = "${concat("db",".", aws_route53_zone.primary.name)}"
  zone_id = "${aws_route53_zone.primary.zone_id}"
  type = "A"
  records = [ "${aws_instance.db.public_ip}" ]
  ttl = "1"
}

Il n’y a qu’un seul serveur de base de donnĂ©es, l’attribut count est absent. Cependant, l’absence de count n’a pas exactement le mĂŞme comportement que count = 1 (. En consĂ©quence, si une instance est prĂ©vue pour ĂŞtre scalable, il est prĂ©fĂ©rable d’utiliser le paramètre count avec la valeur 1. Notons Ă©galement que count peut ĂŞtre nul, fournissant ainsi un levier pour dĂ©sactiver, dans certain cas, tout un pan de la configuration.

Loadbalancer
# Load balancing
resource "aws_elb" "www" {
  name = "tf-demo-elb"
  # The same availability zone as our instance
  availability_zones = ["${element(aws_instance.www.*.availability_zone, count.index)}"]
  listener {
    instance_port = 80
    instance_protocol = "http"
    lb_port = 80
    lb_protocol = "http"
  }
  instances = ["${aws_instance.www.*.id}"]
}

resource "aws_route53_record" "tf-demo-lb-record" {
  name = "${concat("www",".", aws_route53_zone.primary.name)}"
  zone_id = "${aws_route53_zone.primary.zone_id}"
  type = "CNAME"
  records = [ "${aws_elb.www.dns_name}" ]
  ttl = "1"
}

La gestion du loadbalancing est assez simple, le port 80 du loadbalancer est ici redirigé sur le port 80 des membres de la resource aws_instance.www et une entrée DNS pointe vers www.tf-demo.com.

PrĂŞt au lancement ?

L’infrastructure intĂ©gralement dĂ©crite, installons terraform. Le binaire est distribuĂ© pour chaque plateforme sous la forme d’une archive contenant le client en ligne de commande et les modules pour les providers. Pour les utilisateurs de OS X, il est disponible sur homebrew.

brew update && brew install terraform
terraform -version

La version utilisée dans cet article est la 0.3.5 et certaines ressources ne fonctionneront pas avec une version inférieure.

terrafom plan 

Avant de se lancer, prĂ©visualisons l’impact de notre configuration : terrafom plan affiche le plan d’exĂ©cution sans l’appliquer. Cette commande montre par la suite les Ă©carts de configuration avec l’existant.

terraform apply

La configuration peut dĂ©sormais ĂŞtre appliquer sereinement avec terraform apply qui crĂ©e l’ensemble de la plateforme la première fois puis applique les modifications par la suite. Le fichier terraform.tfstate est alors crĂ©Ă©. Ce fichier est primordial, il contient l’Ă©tat du projet indispensable pour dĂ©finir les opĂ©rations de mise Ă  jour. Il est donc important de le stocker en dehors du projet et de s’assurer de sa synchronisation. Dans ce but, terraform propose de stocker cette Ă©tat sur un serveur distant, http par exemple, en utilisant les commandes terraform push et terraform pull. Par dĂ©faut l’Ă©tat est conservĂ© sur disque, dans le rĂ©pertoire du projet.

terraform destroy

Lorsque la plateforme n’est plus utile, vous pouvez la dĂ©truire avec la commande destroy. Attention nĂ©anmoins, les instances EC2 sont dĂ©truites et non suspendues, les donnĂ©es locales sont perdues.

Conclusion

Terraform se concentre sur un objectif bien dĂ©fini, la crĂ©ation d’infrastructure, et le fait bien. Le choix a clairement Ă©tĂ© fait de dĂ©lĂ©guer le provisionning aux outils dĂ©jĂ  existant. Reconnaissons cependant que l’interaction avec ces outils est pour le moment tĂ©nue, se limitant Ă  une simple exĂ©cution de commande. L’utilisation de scripts ou d’outils tiers est encore nĂ©cessaire.

Chaque nouvelle version de Terraform apporte son lot de nouveautĂ©s et comble petit Ă  petit les manques les plus bloquants, suffisamment du reste pour que l’ensemble soit utilisable. Les premières versions souffraient d’un Ă©tat parfois instable, les dernières ont trouvĂ© le remède. D’une part les plugins ont gagnĂ© en stabilitĂ©, d’autre part le choix d’un fichier d’Ă©tat au format JSON assure de pouvoir lire et corriger un Ă©ventuel problème.

Parmi les fonctionnalitĂ©s Ă  venir, notons l’adoption d’une DSL pour les variables en remplacement de l’interpolation permettant par exemple l’utilisation de fonctions mathĂ©matiques ou l’ajout dans l’API des providers d’une mĂ©thode vĂ©rifiant l’existence Ă  priori d’une ressource.

Les sources de l’exemple sont disponibles sur github : https://github.com/tauffredou/terraform

 

 

Catégories: Blog Société

Les promesses en AngularJS (2/3)

Blog d’Ippon Technologies - lun, 01/26/2015 - 14:00

Nous avons vu dans l’article prĂ©cĂ©dent en quoi consistait une promesse et comment fonctionnent les callbacks. Nous allons Ă  prĂ©sent voir les deux principaux utilisateurs de promesses dans AngularJS Ă  savoir les services $http et $resource et quelles sont leurs spĂ©cificitĂ©s.

Les services $http et $resource Le service $http

Nous avons vu que pour greffer des callbacks Ă  une promesse il fallait forcĂ©ment utiliser then(). Et bien, ce n’est pas totalement vrai, du moins pas ici. Si c’est effectivement la bonne approche pour les promesses faites maison, celles renvoyĂ©es par les services $http et $resource en revanche nous exposent des fonctions supplĂ©mentaires plus pratiques pour traiter les rĂ©sultats renvoyĂ©s. Je ne voulais juste pas commencer cette prĂ©sentation avec des exceptions dès les premières lignes de code. Voici les fonctions spĂ©cifiques Ă  $http que vous utiliserez pour rĂ©cupĂ©rer le rĂ©sultat de vos promesses :

success(function(data, status, headers, config)
error(function(data, status, headers, config)

Et voici un cas d’utilisation tirĂ© directement de la documentation de $http :

$http.get('/users/1').success(function(data, status, headers, config) {
    // this callback will be called asynchronously when the response is available

    }).error(function(data, status, headers, config) {
    // called asynchronously if an error occurs or server returns response with an error status

});

Cela revient exactement Ă  faire un then(successCallback, errorCallback) Ă  la diffĂ©rence qu’ici le rĂ©sultat de la promesse est dĂ©coupĂ© en 4 arguments distincts et ce sont ces derniers que l’on reçoit en arguments aux callbacks. Il est donc plus intĂ©ressant d’utiliser success() et error() qui sont plus explicites quant aux rĂ©sultats envoyĂ©s par $http.

Vous trouverez ici un petit exemple d’appel Ă  $http.get() utilisant then(), success(), error(), catch() ou encore finally().

Sachez Ă©galement qu’il est possible avec $http de configurer des « interceptors » qui vous permettront d’intercepter toutes les requĂŞtes ou les rĂ©ponses qui passent par $http, donc respectivement entre la requĂŞte de votre application et le serveur et entre la rĂ©ponse du serveur et votre application. Ces interceptors sont en fait eux-mĂŞmes des promesses qui peuvent ĂŞtre rĂ©solues ou rejetĂ©es indĂ©pendamment de la requĂŞte initiale. On pourrait donc imaginer une gestion d’erreur centralisĂ©e oĂą toutes les erreurs de type 404 NOT FOUND sur des images seraient interceptĂ©es afin de renvoyer une image par dĂ©faut Ă  la place. Le code appelant recevrait donc une promesse rĂ©solue avec une image par dĂ©faut au lieu d’une promesse rejetĂ©e comme cela se serait produit sans l’interceptor.

Le service $resource

Ce service a Ă©tĂ© spĂ©cialement conçu pour interagir avec des API RESTful. Il s’agit en rĂ©alitĂ© d’une couche au dessus de $http qui facilite l’Ă©criture de vos requĂŞtes ainsi que la manipulation des rĂ©sultats en sortie. La syntaxe est pour le coup très diffĂ©rente de $http :

var user = $resource('/users/:userId').get({userId: 1});

Ici beaucoup de choses se passent : dans un premier temps, on voit que l’on fournit une URL Ă  un objet de classe $resource comme on l’aurait fait avec $http, Ă  la diffĂ©rence qu’ici on peut y mettre des paramètres optionnels. On appelle ensuite la mĂ©thode get() sur cet objet et Ă  qui on fournit justement la valeur du paramètre optionnel. Jusque lĂ , la diffĂ©rence avec $http semble minime, nĂ©anmoins vous aurez peut-ĂŞtre remarquĂ© deux choses :

  1. On a directement affecté le retour de la méthode get() à une variable user
  2. Il n’y a pas de then() ou de callback Ă  la suite de get()

La raison est très simple : ce n’est pas une promesse que la mĂ©thode get() renvoie, mais un objet d’instance $resource qui reprĂ©sente la future donnĂ©e renvoyĂ©e. Si cet objet ne reprĂ©sente pas vĂ©ritablement la promesse, il est tout de mĂŞme possible de la rĂ©cupĂ©rer par le biais de l’attribut $promise sur l’instance $resource :

$resource('/users/:userId').get({userId: 1}).$promise.then(function(value) {
    // successCallback

});

NĂ©anmoins cela n’est pertinent que si vous avez explicitement besoin de la promesse. Si votre besoin se rĂ©sume simplement Ă  rĂ©cupĂ©rer un rĂ©sultat asynchrone, alors vous pouvez simplement utiliser la variable « user » Ă  qui vous avez affectĂ© le retour du get() et l’utiliser directement dans votre template HTML. En effet, cette dernière sera automatiquement remplacĂ©e par les donnĂ©es rĂ©elles renvoyĂ©es par l’instance $resource. En clair, la variable « user » ici reprĂ©sente les donnĂ©es futures de votre requĂŞte sans avoir Ă  passer par un callback de succès comme vous auriez dĂ» le faire avec une promesse. C’est d’ailleurs lĂ  toute la force de $resource car il nous Ă©vite de mettre Ă  jour explicitement la valeur comme avec $http :

var user = {};

$http.get('/users/1').then(function(value) {
    user = value;
});

Oui mais si on veut quand même faire du traitement métier à la fin de la requête ? Faut-il forcément travailler avec la promesse originelle via $promise et appeler then() ?

On peut effectivement faire comme ça, mais le plus pratique est de passer par les callbacks de succès et d’erreur que l’on peut envoyer aux actions de l’objet d’instance $resource. Car oui, dans l’exemple prĂ©cĂ©dent on s’est contentĂ© de faire get({userId: 1}) sur la classe $resource mais en rĂ©alitĂ© cette « action » peut avoir trois arguments. Et ces deux arguments supplĂ©mentaires sont justement les callbacks de succès et d’erreur auxquels nous sommes Ă  prĂ©sent habituĂ©s. Voici la signature que prĂ©sente la documentation officielle pour toutes les actions de type GET en HTTP :

Resource.action([parameters], [success], [error])

Petite parenthèse : La raison pour laquelle la documentation utilise le terme « action » ici et non de fonctions est très simple : il est possible de définir ses propres actions à la construction de la $resource et de définir leur signification HTTP ainsi que divers paramètres. Je pourrais donc si je le voulais créer une action recupere() qui en fait ferait la même chose que get().

La signature présentée précédemment ne concernent que les actions de type GET en HTTP. Il y a encore deux autres signatures pour deux situations supplémentaires :

  1. Les actions de type non GET sur la classe Resource :
    Resource.action([parameters], postData, [success], [error])
  2. Les actions de type non GET sur un objet d’instance Resource :
    instance.$action([parameters], [success], [error])

Notez la prĂ©sence du symbole dollar « $ » pour les instances de $resource qui du coup va utiliser les donnĂ©es de l’instance dans le request body, tandis que la mĂ©thode de la classe $resource nĂ©cessite qu’on lui fournisse les donnĂ©es Ă  envoyer. Je ne vais pas m’Ă©tendre dessus mais je vous invite fortement Ă  voir la documentation pour bien assimiler la nuance entre la « classe » $resource et les « instances » de $resource.

Au final voici une utilisation de $resource classique dans laquelle on a Ă©galement besoin d’effectuer du mĂ©tier dans des callbacks de succès ou d’erreur :

var user = $resource('/users/:userId').get({userId: 1}, function(data) {
    // successCallback

    }, function(error) {
    // errorcallback

});

Ce sera tout pour le service $resource. Comme pour $http, vous trouverez ici un exemple d’appel Ă  $resource().get() dans lequel les diffĂ©rents types d’appels possibles sont couverts.

 

Ce deuxième article sur la prĂ©sentation des promesses dans AngularJS est Ă  prĂ©sent terminĂ©. Nous avons vu ensemble les bases des promesses ainsi que les diffĂ©rents services d’AngularJS qui les utilisent, mais nous n’avons pas encore vu comment ces dernières fonctionnaient vĂ©ritablement en interne ni comment crĂ©er ses propres promesses. Tout cela sera couvert dans le troisième et dernier article de cette prĂ©sentation.

Catégories: Blog Société

Craftsmanship : Zenika derrière le rideau

Zenika - lun, 01/26/2015 - 14:00

Cela fait quelques années déjà que des communautés se forment autour des coding dojos ou assimilables. Au delà de l'aspect technique, ces sessions présentent l'intérêt de pouvoir mener des expérimentations.

Elles offrent ainsi l'opportunité à des développeurs aux pratiques différentes, parfois même opposées, de se rencontrer ainsi que de mettre à l'essai des méthodologies de travail alternatives.

Dans ce cadre, les discussions qui s'engagent à la fin de ces séances sont essentielles: elles permettent de remettre en cause librement les axiomes sur lesquels reposent les méthodologies mises en œuvre au cours du dojo. L'objectif est d'en favoriser l'appropriation par les participants tout en encourageant une application rationnelle et non... Read Craftsmanship : Zenika derrière le rideau

Catégories: Blog Société

Run a cron job with Docker

ekito people - lun, 01/26/2015 - 12:12

ContainersAt Ekito, we adopted Docker as lightweight virtualization solution to deploy our internal servers, as well as deliver “ready to run” applications to our customers.

Bert has already published an excellent article on Docker, one year ago. Since then, we continued to experiment on this topic and I would like to present a very simple (but not trivial) use case:
run a cron job in a docker container.

The source code is available on github.

Install docker

Depending on your platform, you can find the complete documentation on the docker website.

The cron job

We will create a cron job that will display “Hello world”, every minute, in the console

Let’s create a new file called “crontab” to describe our job.

* * * * * root echo "Hello world" >> /var/log/cron.log 2>&1
# An empty line is required at the end of this file for a valid cron file.

This job will echo “Hello world”, every minutes, and redirect the output in the file /var/log/cron.log

Important remarks:

  • a blank line is required at the end of this file!
  • the job is run by the “root” user as it is the only user that will exist in the container
The docker image

The following DockerFile describes all the steps to build your image

FROM ubuntu:latest
MAINTAINER docker@ekito.fr
 
# Add crontab file in the cron directory
ADD crontab /etc/cron.d/hello-cron
 
# Give execution rights on the cron job
RUN chmod 0644 /etc/cron.d/hello-cron
 
# Create the log file to be able to run tail
RUN touch /var/log/cron.log
 
# Run the command on container startup
CMD cron && tail -f /var/log/cron.log

Then you can build the image with

sudo docker build --rm -t ekito/cron-example .

And run it:

sudo docker run -t -i ekito/cron-example

Be patient, wait for 2 minutes and your commandline should display:

Hello world
Hello world

Now you can create you own script to backup you data, check your system status, or whatever you want !

The post Run a cron job with Docker appeared first on ekito people.

Catégories: Blog Société

Paris JUG : On a testé pour vous le Young Blood II

Format

parisjugDans un amphithéâtre de plusieurs dizaines de places, 6 speakers présélectionnés se sont succédés pour nous présenter un sujet de leur choix, disposant de 15 minutes chacun, suivies de 5 minutes de questions / réponses. Le tout animé par un chauffeur de salle survolté.

Le milieu de la soirée est marqué par un entracte, au cours duquel un buffet nous est offert par le sponsor de la soirée, Innovation Box. Pendant ce temps, un QCM décalé nous est posé concernant les présentations de la soirée, sûrement pour vérifier notre assiduité.

A l’issue des présentations, l’auditoire est invité à voter pour ses présentations préférées.

WebCrypto API

Ou comment chiffrer ses données via Javascript dans un navigateur web moderne… (par Jean-Christophe Sirot)

Jusqu’en 2012, et malgrĂ© la prĂ©sence de librairies tierces, il n’existait pas d’API JavaScript performante pour effectuer du chiffrage / dĂ©chiffrage, et protĂ©ger ses donnĂ©es, hormis SSL. Cependant, SSL permet seulement de chiffrer une communication entre un client et un serveur. Il existait nĂ©anmoins des solutions basĂ©es sur des applets Java.

Avec l’apparition de nouvelles applications riches, de nouveaux besoins apparaissent, et notamment celui de chiffrer des données au sein même du navigateur (par exemple pour un coffre fort électronique).

Il existe plusieurs raisons pour lesquelles JavaScript ne proposait pas, jusqu’ici, de solution de chiffrage :

  • il est incapable de gĂ©nĂ©rer des nombres alĂ©atoires de manière non prĂ©dictible,
  • le langage ne propose pas de tableaux performants, ni d’entiers 64 bits, ou big integer, indispensables si l’on souhaite implĂ©menter des algorithmes de cryptographie,
  • impossibilitĂ© de rĂ©aliser des calculs long dans le navigateur (calculs de clĂ©s de chiffrage) car un seul thread exĂ©cute le JavaScript dans un navigateur.

Après de longs mois de gestation, le W3C a donné naissance à de nouvelles APIs(http://www.w3.org/TR/WebCryptoAPI/#examples-section), parmi lesquelles, un ensemble de primitives prêt à l’emploi au sein de l’objet window.crypto.

Par ailleurs, l’implĂ©mentation toute fraĂ®che des promesses (processus asynchrones) s’avère salutaire lorsqu’il est nĂ©cessaire d’effectuer des calculs longs.

Exemple d’utilisation de window.crypto :

// plusieurs opération possibles : encrypt / decrypt / sign / verify / generateKey ou digest
window.crypto.subtle.digest({ name: "SHA-256" }, data);
// générateur de nombres aléatoires
window.crypto.getRandomValues(new Uint32Array(10));
// déchiffrage d’un message en précisant une clé et un algorithme
var iv = window.crypto.getRandomValues(new Uint8Array(16))
var algo {
  name: "AES-GCM",
  iv: iv
}
return window.crypto.subtle.decrypt(algo, key, message);

Nonobstant les quelques limitations de cette jeune API, il est désormais possible de faire du chiffrage dans notre navigateur web, et la plupart des algorithmes communément utilisés sont proposés. De plus, l’API est gelée, et permet donc d’être utilisée sans être obligé de revoir son code après chaque montée de version du navigateur.

Concernant les limitations, cette recommandation du W3C :

  • ne nous dispense pas de devoir faire confiance Ă  l’application web,
  • n’est pas encore disponible sur tous les navigateurs (Can I Use Cryptography ?),
  • n’est pas non plus utilisable avec les cartes Ă  puces,
  • ne permet pas encore de chiffrer de gros objets (streaming),
  • ne propose pas tous les algorithmes de chiffrement

Le conseil avisĂ© de notre speaker : plutĂ´t que de faire de l’à-peu-près, si l’on doit utiliser WebCrypto sur un projet, mieux vaut demander conseil, ou effectuer un audit le cas Ă©chĂ©ant.

Circuit Breaker Pattern

Ou comment accroître la tolérance d’un système aux pannes (par Mouhcine Moulou)

Combien de fois a-t-on butĂ© sur des problĂ©matiques de timeouts qui nous font perdre non seulement un temps prĂ©cieux, mais qui – et c’est terrible – se terminent rĂ©gulièrement en exception… Exceptions qui sont en gĂ©nĂ©ral brutalement stoppĂ©es dans leur Ă©lan (pas l’animal) par de gros try-catchs poilus, vraiment.
A l’image d’un disjoncteur qui coupe le courant pour empêcher la propagation d’une panne à tout une installation électrique, le Pattern Circuit Breaker fait office de proxy qui n’appelle plus les services si ces derniers sont tombés sur le champ de bataille.

Exemple de code Java utilisant ce pattern :

// utilisation de l'implémentation d'Akka
CircuitBreaker breaker = new CircuitBreaker(...);
breaker.callWithCircuitBreaker( new Callable<Future<String>>() { ... } );

 

Le breaker connaît l’état du service cible grâce à plusieurs règles paramétrables, telles que le “max-failures”. Si ce “max-failures” est atteint, le breaker s’ouvre et retourne immédiatement une exception à chaque appel. On nomme ce principe le “let-it-crash”. Provoquer nous même un échec nous permet d’effectuer un “handle-with-grace” de l’exception.

Après une durée appelée “reset-timeout” à l’état open, le Circuit Breaker se met dans un état dit “half-open” où il laisse passer un appel vers le service tiers, pour tâter le terrain.

Si le service est de nouveau disponible, le Breaker se referme et les appels ne sont plus interrompus prématurément. Au contraire, si l’appel échoue, le Breaker se rouvre, et ainsi de suite.

 

(source : http://doc.akka.io/docs/akka/snapshot/common/circuitbreaker.html)

 

Ce Pattern semble convenir plus particulièrement à des architectures type “micro-services”, au sein desquelles le système doit rester réactif malgré la multiplication des briques. En outre, il offre aussi la possibilité d’y connecter des outils de monitoring, selon l’API utilisée. On ne va pas se mentir, un tel pattern nous permet avant tout d’économiser des ressources (essentiellement mémoire) et de répondre plus rapidement au client en attendant la remise en route du servie sous-jacent.

Lors de la session de questions, on apprend que l’implémentation d’Akka ne nous permet pas de filtrer les exceptions levées par les services selon leur type (technique ou fonctionnel).

Ainsi, mettre un Circuit Breaker pour des appels à une base de données peut se révéler contre productif : si les Exceptions sont d’ordre technique (ConstraintException par exemple), le Breaker pourrait s’ouvrir alors que le service est totalement opérationnel.

Le speaker indique qu’un Circuit Breaker doit ĂŞtre utilisĂ© pour “disjoncter” les appels d’un seul et unique service. Il ne doit absolument pas ĂŞtre mutualisĂ© : pour deux services utilisant le mĂŞme Breaker, si l’un tombe, l’autre en pâtit.

Le speaker précise également que ce pattern permet d’éviter le Cascading Failure, c’est à dire l’effet domino et la perte des services s’appelant consécutivement lorsque les erreurs sont mal gérées.

 

Faire tourner une JVM avec 4To de mémoire

Ou comment gérer la mémoire en Java sans native behaviors (par Gaëlle Guimezanes)

La speakerine commence sa présentation en nous introduisant directement dans le contexte : comment faire monter en mémoire vive une montagne de données (600 millions de tuples et 50 colonnes) relatives à des trades sur des marchés financiers ? Pour corser le tout, on se fixe comme contrainte de conserver Java comme unique langage de programmation.

C’est justement ce que nous explique Gaëlle, à travers une base de données “in-memory” qu’elle développe.

Sur une JVM traditionnelle, et en utilisant de la mĂ©moire “on-heap” garbage collectĂ©e, dès les quelques premiers gigas de donnĂ©es chargĂ©es en RAM l’expĂ©rience touche rapidement Ă  sa fin. En effet, le GC (Garbage Collector) se dĂ©clenche… La JVM explose sous le nombre de dĂ©placements de rĂ©fĂ©rences (Young vers Old Generation) et autres optimisations qui s’avèrent contre productives dans notre cas d’utilisation. En fait, le GC ne sait pas gĂ©rer de tels volumes de donnĂ©es. De plus, nous souhaitons stocker de gros objets, pour une longue durĂ©e (le propre d’une base de donnĂ©es), ce qui va Ă  l’encontre de « l’hypothèse gĂ©nĂ©rationnelle faible », et ce n’est pas forcĂ©ment ce que prĂ©fère le GC.

Nous sommes donc contraints de sortir de la zone de mémoire scrutée par le GC. Il est nécessaire de pénétrer dans un univers hostile, le “off-heap”.

Une utilisation naïve de l’API nous fait choisir en premier lieu un ByteBuffer(http://docs.oracle.com/javase/6/docs/api/java/nio/ByteBuffer.html), capable de retourner un pointeur sur une zone “off-heap”. Dès lors, une limitation de taille nous est imposée : il est impossible de stocker des objets (sérialisés ou non), on doit se contenter de caractères ou d’entiers primitifs. Un avantage tout de même à cette solution, la mémoire est allouée dans une zone située au plus proche du processeur.

NĂ©anmoins, une fois encore, certaines optimisations de Java crĂ©ent de l’overhead et nous mettent des bâtons dans les roues (la conversion en Little / Big Endian des octets en fonction du système hĂ´te, par exemple).

Sitôt abandonnés les ByteBuffers, une nouvelle classe attire notre attention : Unsafe(http://www.docjar.com/docs/api/sun/misc/Unsafe.html). Pour allouer de la mémoire, à la manière de C, mais cela reste moins indigeste qu’en assembleur (décalage de bits, bonsoir !).

Comment récupérer une instance d’Unsafe de manière tout à fait unsafe ?

// récupération du singleton d'Unsafe par reflexion
Field f = Unsafe.class.getDeclaredField("theUnsafe");
f.setAccessible(true);
Unsafe unsafe = (Unsafe) f.get(null);

Gaëlle nous fait rêver !

Une fois récupérée ladite instance d’Unsafe, nous quittons l’univers Java bisounours où allouer une zone mémoire relève de la magie. On affecte désormais des valeurs directement via des adresses “physiques” en mémoire, avec tous les crashs que cela peut engendrer.

Maintenant que nous sommes en mesure de gérer la mémoire, il nous faut optimiser les calculs. En effet, un processeur pouvant servir plusieurs mémoires vives, d’énormes quantités de données s’engouffrent dans un entonnoir pour s’y coincer lamentablement.

Pour pallier ce problème, Gaëlle utilise un système NUMA (Non Uniform Memory Access) intégré dans un Bullion (http://www.bull.fr/bullion/), machine dopée aux EPO prêtée pour l’occasion par l’entreprise Bull. Lance Armstrong lui-même n’a jamais pris autant de substances dopantes. Sur cette architecture particulière, chaque processeur est servi par une mémoire distribuée. Le couple processeur / mémoire est géré par un Thread qui lui est propre.

En chiffres :

3 minutes : c’est la durée totale d’une requête en NUMA. Il faut compter 1,5 à 3 fois plus de temps pour exécuter cette même requête sur une architecture non NUMA.

10 heures : c’est le temps que prend le garbage collector si 2 To de données sont stockées On-Heap et 3 secondes Off-Heap.

1h20 : c’est le temps qu’il nous faut pour charger presque 4 To de données.

Le défi est relevé, la solution proposée permet d’obtenir des résultats bluffants malgré l’utilisation de Java, notoirement connu pour sa gourmandise en terme de mémoire.

Mais que se passe-t-il en cas de panne ? Il s’avère que chaque calcul est loggué, cette fois ci sur un disque bien dur, ce qui permet de remettre la machine en route et de recharger les données dans l’état ou elles étaient avant le plantage. Il est également possible de repartir de zéro depuis une base de données aggrégées du fournisseur. Dans ce cas on a le temps d’aller prendre un, voire plusieurs cafés, et d’envoyer quelques tweets.

Booster les dev’ avec SpringBoot

Ou comment Ă©viter de trop se soucier de la configuration (par Julien Sadaoui)

Durant cette présentation, on survole rapidement Spring Boot (http://projects.spring.io/spring-boot/) et son principe fondateur : la convention c’est bien, la configuration c’est mal. Il était temps !

Le speaker démarre la présentation en nous montrant une configuration de dépendances Maven pour un projet Spring. Il demande si quelqu’un dans la salle a déjà eu à affronter ce plat de spagghetis. Évidemment, les mains se lèvent.

Pour pallier aux défauts inhérents à Spring, Spring Boot apporte de nombreuses nouveautés :

La première d’entre elles est l’apparition de dépendances starters qui vont remonter pour nous les dépendances tierces. L’avantage principal est que Spring nous certifie que ces versions de dépendances sont testées s’intègrent parfaitement avec la version de Spring utilisée.
Par exemple, le starter spring-data-jpa va remonter Hibernate avec une version sélectionnée aux petits oignons.

Ensuite, le framework va nous apporter tout un tas de configurations par défaut, qu’il nous suffit de surcharger à l’envie, ou d’activer via des annotations salvatrices.

Un autre de ses avantages est qu’il nous permet de tester facilement nos applications. Il propose un ensemble d’outils et de classes pour faciliter l’écriture et la mise en place de tests d’intégration de bout en bout.

Enfin, Spring Boot expose un certain nombre de services REST pour inspecter l’état d’une application en cours d’exĂ©cution, parmi lesquels : /beans /env /info /metrics /trace.

Pour les amateurs de Spring pour le web, Spring Boot embarque automatiquement un Tomcat ou un Jetty, sans qu’il ne soit nécessaire de l’installer soi-même. Un gros plus pour bootstrapper rapidement un projet “from scratch”.

Monitorer sa consommation d’Ă©lectricitĂ© : avec un Raspberry Pi, ActiveMQ, MongoDB et Docker

Ou comment court-circuiter légalement les factures EDF annuelles (par Cédric Finance)

 

Première étape : la connexion au compteur

On peut brancher simplement le Raspberry Pi sur le compteur, c’est légal, et ça se fait via un port série. Muni d’un émetteur wi-fi, de quelques résistances et d’un fer à souder, notre bidouilleur en herbe peut désormais récupérer de jolies données sous la forme :

[none ]HCHP 001521211 ‘
PTEC HC.. S
IINST 001 I
IMAX 008 2
PMAX 06030 3
PAPP 01250 +
…[/none]

 

Seconde étape : le stockage / affichage des données

Dans un premier temps, on stocke les données sur Thingspeak (https://thingspeak.com/). L’outil à la gentillesse de nous apporter une interface de consultation agréable sous la forme de graphiques. Mais très vite Cédric veut pousser l’exercice un cran plus haut.

Ce qui ressemblait jusqu’alors à un passe temps nous fait désormais penser à un projet viable et quasi vendable. Il faudrait juste penser à remplacer la boîte à chaussures dans laquelle se trouve le Raspberry Pi.

A partir de ce moment là, Cédric a été capable de détecter une anomalie sur son installation électrique. Un abominable chauffe-eau se mettait inutilement en route pendant son absence. Ni une, ni deux, Cédric s’empare d’un câble, d’un marteau et d’une tronçonneuse pour entailler la bête et lui faire une opération à coeur ouvert.

 

Troisième étape : l’analyse des données

On abandonne Thingspeak. Les donnĂ©es sont envoyĂ©es vers ActiveMQ qui va stocker tout ça dans une base de donnĂ©e Mongo via un “subscriber”. L’ensemble de ce micro-système est encapsulĂ© dans un conteneur Docker.

Il ne reste plus Ă  CĂ©dric que d’implĂ©menter sa propre interface de monitoring, capable d’aller lire les informations reçues en temps rĂ©el.

On peut imaginer de nombreuses applications à ce petit dispositif ingénieux, et même simplifier ce dernier en remplaçant le Raspberry Pi par un Spark Photon.

On peut aussi imaginer de nombreuses améliorations possibles. Cédric nous en cite quelques-unes, qui sont dans la Roadmap… graphes en fonction des périodes ; interpolation des données manquantes ; calcul du coût relatif à la consommation réelle ; ajout de Docker Compose.

 

Applications du type Optional

Ou “Apprendre à coder en Java 8, pour les nuls” (par Fabrice Sznajderman)

 

Pour tous les briscards du code Java, un tel bout de code représente le mal, le vrai Malin, le suppôt de Satan du code :

if (contact == null) {
  ...
}

 

Les checks-null : la terreur des mappers ! Et ça, on n’en veut plus. On veut du code qui soit porteur de sens, et pas du code qui nous protège contre Satan en personne : les NullPointerExceptions.

Ce genre de code n’a aucune utilité métier et pollue souvent la lisibilité des méthodes.

Pour se débarrasser de tels bouts de code, il est possible d’utiliser le type Optional (http://docs.oracle.com/javase/8/docs/api/java/util/Optional.html). Il s’agit d’un type monadique : le speaker nous explique cette notion abstraite comme étant une espèce de capsule permettant d’appliquer des primitives sur son contenu, indifféremment du type de contenu (chaînes de caractères, entiers, ou même des fonctions).

Grâce à la magie des Optional, on peut se débarrasser des checks-null.

Pour sa session de live-coding, Fabrice a choisi un exemple de la vie courante en proposant un service de Contact exploitant un repository. La méthode findById(long id), avant le refactoring, renvoie un Contact.

Que se passe t-il si l’Id ne correspond à aucun contact ? La méthode retourne null !

En refactorant la méthode de cette manière :

public Optional<Contact> findById(long id) {
  return Optional.ofNullable(contactRepository.findById(id));
}

 

On s’assure ainsi que la méthode renverra uns structure de données représentant une valeur potentiellement absente.

Il nous reste plus qu’à utiliser l’Optional dans notre méthode appelante :

Optional<Contact> optional = contactService.findById(5);
if (optional.isPresent()) {
  System.out.println(“Le contact a ” + optional.get().getAge() + “ ans”);
} else {
  System.out.println(“Le contact n’a pas été trouvé”);
}

 

Cependant, même si le pattern if-null a disparu, la structure conditionnelle est toujours présente et continue de polluer le code.

On peut donc pousser l’exercice un cran au dessus et frôler la perfection en appliquant un petit trait fonctionnel à un langage des plus impératifs :

Optional<String> message = optional.map(c -> “La contact a ” + c.getAge() + “ ans”).orElse(“Le contact n’a pas été trouvé”);
System.out.println(message.get());

 

Cette portion de code permet de transformer un Optional<Contact> en Optional<String>, en conditionnant la chaîne de caractère à la présence d’un contact ou non. Si le contact est présent, on affiche une chaîne contenant son âge, sinon on affiche un message arbitraire. On élimine ainsi toutes les fioritures techniques, et la fluent API permet de lire le code aussi simplement qu’une phrase !

Pour ceux qui voudraient bénéficier de cet objet magique sur leurs projets préhistoriques en Java 7, Guava (https://github.com/google/guava) propose une implémentation assez proche de celle présente dans Java 8, à l’instar de la relation entre JodaTime (http://www.joda.org/joda-time/) et la nouvelle API java.time.

Le type Optional permet donc de représenter une valeur potentiellement absente. Le speaker a également précisé que ce type permettait également de documenter automatiquement le code. En effet, plutôt que d’avoir un commentaire erroné du type “cette méthode ne renverra jamais null”, la sémantique même du type Optional permet de renseigner le développeur sur le fait que la méthode peut, potentiellement, ne pas renvoyer de valeur utile. Et le tout de manière typée !

 

Ce que nous retiendrons de cette soirée

Nous avons pu assister à une soirée somme tout agréable, avec des talks et des speakers de qualité. L’ensemble était très bien organisé et bien mené par les organisateurs, qui ont ponctué les présentations de petits interludes croustillants.

Portant sur des sujets très hétérogènes, il est difficile de classer toutes les présentations les unes par rapport aux autres. Il nous est tout de même possible d’élire notre TOP 2 : la JVM surboostée et le Raspberry-Pi survolté. C’est d’ailleurs ce dernier talk, présenté par Cédric Finance, qui a remporté le vote du public. Il aura l’opportunité de présenter son installation à Devoxx 2015 (http://www.devoxx.fr/).

Ce format, à l’instar des Human Talks, permet en peu de temps de parcourir un ensemble de sujets hétérogènes. Nous avons maintenant hâte de découvrir ce que nous réserve la prochaine édition !

Catégories: Blog Société

Les promesses en AngularJS (1/3)

Blog d’Ippon Technologies - ven, 01/23/2015 - 14:58

Depuis maintenant quelques annĂ©es, la vague AngularJS dĂ©ferle et un grand nombre de projets orientĂ©s « Front » l’adoptent presque par dĂ©faut dĂ©sormais. En effet, nous sommes arrivĂ©s Ă  un stade oĂą mĂŞme les clients les moins avertis n’hĂ©sitent plus Ă  mentionner AngularJS pour leurs projets, garantis d’ĂŞtre Ă  l’Ă©tat de l’art (du moins jusqu’Ă  l’arrivĂ©e d’AngularJS 2.0 qui va faire table rase de l’existant, mais ceci est une autre histoire).

En consĂ©quence, il y a donc de plus en plus de dĂ©veloppeurs qui sont propulsĂ©s sur des projets AngularJS et qui peuvent bloquer sur des notions fondamentales du framework : l’injection de dĂ©pendances, les directives, le $scope ou encore les promises. Vous l’aurez donc compris, cet article est dĂ©diĂ© aux promises en AngularJS. Bien que ces API seront sans doute balayĂ©es par l’intĂ©gration native des promesses en ECMAScript 6, nombreux seront encore les projets qui s’appuieront sur AngularJS 1.x ; il est donc plus que jamais pertinent d’en comprendre le fonctionnement.

Cette prĂ©sentation sera en trois articles : dans celui-ci nous verrons tout d’abord qu’est-ce qu’une promesse et comment utiliser les callbacks ; le deuxième se concentrera sur les diffĂ©rents services d’AngularJS qui les utilisent Ă  savoir $http et $resource ; enfin le dernier sera quant Ă  lui consacrĂ© Ă  la crĂ©ation de nos propres promesses Ă  l’aide de la librairie Q.

Qu’est-ce qu’une « promesse »

Avant d’aller plus loin, il faut d’abord dĂ©finir ce qu’est une promesse. Pour cela, je vais m’appuyer sur l’excellente dĂ©finition de CommonJS qui est d’ailleurs citĂ©e par la documentation d’AngularJS : une promesse est un objet reprĂ©sentant le rĂ©sultat futur d’une action exĂ©cutĂ©e de manière asynchrone, pouvant donc terminer Ă  n’importe quel moment. Il nous est possible d’y greffer des callbacks de succès et d’erreur, respectivement lorsque la promesse est rĂ©solue ou rejetĂ©e, afin de pouvoir traiter le rĂ©sultat renvoyĂ© par la promesse.

Il faut savoir que les promesses sont intensivement utilisĂ©es dans AngularJS par le biais de ses services : $http, $resource, $timeout, etc. L’exemple de promesse le plus simple serait justement un GET avec le service $http :

$http.get('/users/1');

Cette action est par nature asynchrone puisqu’elle nĂ©cessite de faire une requĂŞte HTTP et utilise donc Ajax. Par consĂ©quent, comment faire pour rĂ©cupĂ©rer le rĂ©sultat du GET sans pour autant attendre la fin de celui-ci et bloquer le traitement ? C’est lĂ  que les promesses interviennent :

var promise = $http.get('/users/1');

promise.then(function(value) {
    // successCallback

    console.log(value);
});

Comme on peut le voir ci-dessus, on stocke le rĂ©sultat de la mĂ©thode $http.get() dans une variable que l’on appelle « promise » car c’est effectivement une promesse que le service $http nous renvoie. Cela veut dire que si on voulait rĂ©cupĂ©rer immĂ©diatement la valeur de promise juste après l’avoir initialisé nous n’obtiendrions rien car la promesse n’a pas encore Ă©tĂ© rĂ©solue. Pour cela, nous avons les callbacks. Le callback de succès justement, reprĂ©sentĂ© par la fonction contenue dans then(), prend en argument le rĂ©sultat renvoyĂ© par la fonction asynchrone – Ă  savoir les donnĂ©es de l’utilisateur dans notre exemple. Il nous est alors possible de logger le dĂ©tail de notre utilisateur Ă  l’intĂ©rieur du callback de succès.

La fonction then() est une des fonctions qu’exposent les objets de type promesse et permet d’appeler des callbacks de succès ou d’erreur selon le rĂ©sultat de la tâche asynchrone. Avant d’aller plus loin, voici la signature de la mĂ©thode then() :

then(successCallback, errorCallback, notifyCallback)

Dans notre exemple prĂ©cĂ©dent je n’ai fourni que le premier argument Ă  la mĂ©thode then() car je n’Ă©tais pas intĂ©ressĂ© par le cas d’erreur. Pour l’instant je ne parlerai pas du troisième argument Ă  savoir le callback de notification ; ce point sera adressĂ© en fin d’article. Cependant voici Ă  quoi ressemble un exemple avec tous les callbacks :

$http.get('/users/1').then(function(value) {
    // successCallback

    }, function(reason) {
    // errorCallback

    }, function(value) {
    // notifyCallback

});

Avant d’aborder les choses vraiment intĂ©ressantes telles que les chaĂ®nes de promesses et la librairie Q, il faut d’abord faire un petit point sur les services $http et $resource et leurs spĂ©cificitĂ©s. En effet, ces derniers utilisent intensivement les promesses et ils reprĂ©senteront certainement 90% des promesses que vous manipulerez dans votre application par consĂ©quent ils mĂ©ritent une partie rien que pour eux. Mais cela sera dans le prochain article de cette prĂ©sentation !

Catégories: Blog Société

Annonce TechEvent Docker Quick Start

Docker_container_engine_logo.pngVous avez certainement déjà entendu parler dans votre entourage de Docker ou de container.

Non, l’informatique ne mute pas au point de s’orienter vers la marine marchande ! Docker est un outil de dĂ©ploiement d’applications empaquetĂ©es dans une entitĂ© appelĂ©e container. Docker regroupe et harmonise des briques technologiques du noyau Linux qui existent depuis quelques annĂ©es (control groups, namespace, etc…).

Docker est une alternative sĂ©duisante aux machines virtuelles grâce Ă  sa lĂ©gèretĂ©. C’est une des raisons qui ont poussĂ© beaucoup de dĂ©veloppeurs Ă  l’employer pour tester de nouvelles technologies ou amĂ©liorer leur intĂ©gration continue. Dans une structure « DevOps », Docker ne s’adresse pas uniquement aux dĂ©veloppeurs, c’est un point de contact technique entre les dĂ©veloppeurs et les opĂ©rationnels.

Que vous soyez dĂ©veloppeur ou opĂ©rationnel, Xebia vous propose de participer un Hands on d’initiation afin de comprendre les concepts fondamentaux de Docker. Cela sera pour vous l’occasion de lancer des containers, de crĂ©er des images ou encore de faire communiquer entre elles deux applications dĂ©ployĂ©es dans des containers.

Pour participer, aucune connaissance de l’outil Docker n’est requise. Il vous faudra cependant avoir la capacitĂ© de vous connecter en SSH Ă  une machine prĂ©-configurĂ©e par nos soins.

Ce Hands on sera certainement suivi de futurs TechEvents sur une utilisation plus avancée de Docker.

Date : le 5 février 2015 à 19h

Lieu :  Xebia
156 boulevard Haussmann Ă  Paris, 75008 Paris
Immeuble A – 7ème étage

Prix: Gratuit, buffet campagnard compris

Si ce TechEvent vous intéresse, vous pouvez dès à présent vous inscrire sur Eventbrite.

Catégories: Blog Société

Legacy code – Se défaire des dépendances statiques

Depuis quelques années, et particulièrement ces derniers mois, le mouvement Software Craftsmanship gagne du terrain et convainc de plus en plus de développeurs et de DSI.
Si les valeurs qu’il soutient sont relativement bien comprises, une interrogation revient rĂ©gulièrement : "Comment appliquer tout cela sur le legacy code?"

Lors de la dernière rĂ©union du Paris Software Craftsmanship, cette question est revenue Ă  l’ordre du jour et nous a donnĂ© l’idĂ©e de cet article.
L’objectif est de vous prĂ©senter des techniques et astuces pas nĂ©cessairement nouvelles, connues de certains mais au combien utiles et adaptĂ©es Ă  la rĂ©alitĂ© quotidienne du legacy code.

Au menu du jour, les dépendances fortes qui se rapportent souvent à des appels statiques. 

Avant de commencer

Pour Ă©tayer nos propos, nous allons nous appuyer sur le code d’un exercice de refactoring proposĂ© par Sandro Mancuso, il y a quelques annĂ©es.
N’hĂ©sitez pas Ă  consulter cette vidĂ©o qui dĂ©taille d’autres concepts non abordĂ©s dans cet article.

Vous retrouverez tous les exemples mentionnés sur notre repository GitHub, où nous avons forké le projet original.
Chaque jalon important correspondra Ă  un tag. Enfin, nous nous concentrerons sur le langage Java mais sachez que d’autres versions sont disponibles (C++, C#, Php, Python et Scala).

Le legacy code

Entrons dans le vif du sujet et découvrons ce qui va constituer notre legacy code :

public class TripService {

   public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
      List<Trip> tripList = new ArrayList<Trip>();
      User loggedUser = UserSession.getInstance().getLoggedUser();
      boolean isFriend = false;
      if (loggedUser != null) {
         for (User friend : user.getFriends()) {
            if (friend.equals(loggedUser)) {
               isFriend = true;
               break;
            }
         }
         if (isFriend) {
            tripList = TripDAO.findTripsByUser(user);
         }
         return tripList;
      } else {
         throw new UserNotLoggedInException();
      }
   }
   
}

Il s’agit d’un service mĂ©tier dont la responsabilitĂ© est de traiter des voyages.
La méthode présentée ici se charge :

  • de rĂ©cupĂ©rer les voyages d’un utilisateur si celui-ci est ami avec l’utilisateur connecté ;
  • de gĂ©rer les exceptions Ă  cette règle (pas d’utilisateur connectĂ©, utilisateurs qui ne sont pas amis).

Ce service n’est couvert par aucun test unitaire et c’est bien Ă©videmment lĂ  l’objectif premier de l’exercice proposĂ© par Sandro.
Avant de démarrer, prenons le temps de rappeler quelques fondamentaux.

Quelques rappels

Il convient de s’entendre sur une dĂ©finition du legacy code. Nous proposons la suivante, communĂ©ment admise mais peut ĂŞtre incomplète selon les contextes.

Un legacy code est un code non testé.

D’autre part, et comme le rappelle Sandro, aucun code de production ne peut ĂŞtre modifiĂ© s’il n’est pas couvert par des tests unitaires.
Autrement dit, pas de refactoring sans filet de sécurité. Seules les actions automatisées par les IDE sont admises dans le cas où elles sont strictement nécessaires pour écrire un test, ce que nous allons voir dans la suite de cet article.

Allez, trĂŞve de bavardages, c’est parti!

Isolation de la thin layer

Notre but est donc de mettre en place les tests unitaires sur notre legacy code pour se permettre de le modifier par la suite.
Une technique classique est de tester en premier lieu les branches de code les moins profondes, c’est Ă  dire celles situĂ©es le plus Ă  gauche.
La raison à cela est simple : plus une branche est profonde, plus elle nécessite de préparation pour y accéder.

Ainsi, le premier test que nous allons chercher Ă  Ă©crire est celui oĂą aucun utilisateur n’est connectĂ© (une exception est alors attendue).
Cependant, quelque chose nous empĂŞche dĂ©jĂ  d’y parvenir :

User loggedUser = UserSession.getInstance().getLoggedUser();

Notre code fait usage d’un appel statique pour rĂ©cupĂ©rer la session puis l’utilisateur connectĂ© Ă  partir de cette dernière. C’est ce que nous appelons une dĂ©pendance forte.
Cette dernière nous dĂ©range car nous n’avons pas la main sur son comportement.

Idéalement, nous souhaiterions simuler ce dernier.  Une première solution consiste à utiliser un framework comme PowerMock. Nous vous le déconseillons fortement.
D’une part, ce dernier est bien plus lent qu’un framework de tests unitaires classique. D’autre part, vous ne feriez rien d’autre que cacher la poussière sous le tapis, sans corriger le rĂ©el problème de votre code. 

En lieu et place, nous allons extraire cette dépendance dans une méthode. Pour ce faire, nous nous appuyons sur notre IDE (rappelez-vous la règle énoncée plus haut). 

protected User getLoggedUser() {
   return UserSession.getInstance().getLoggedUser();
}

Notre expression initiale a désormais la forme suivante :

User loggedUser = getLoggedUser();

Le fait d’avoir dĂ©clarĂ© notre mĂ©thode avec la visibilité protected va nous permettre de proposer une nouvelle implĂ©mentation dans notre classe de tests :

public class TripServiceTest {
 
 private final TripService tripService = new TestableTripService();

    private class TestableTripService extends TripService {

        @Override
        protected User getLoggedUser() {
            return null; // Desired behavior
        }
    }
}

Nous avons maintenant la main sur le comportement de notre dépendance, sans pour autant avoir pris le risque de modifier le code de production.
Le test que nous cherchons à écrire est maintenant trivial :

@Test
public void should_throw_exception_when_no_logged_in_user() {

    // Arrange
    final User unusedUser = null;

    // Act
    catchException(tripService).getTripsByUser(unusedUser);

    // Assert
    assertThat(caughtException()).isInstanceOf(UserNotLoggedInException.class);
}

Note : nous faisons ici usage des librairies AssertJ et Google Catch Exception qui apportent une touche de lisibilité intéressante mais ne sont pas liées aux techniques présentées. 

Nous traitons de la mĂŞme manière l’autre dĂ©pendance forte de notre code. La ligne…

tripList = TripDAO.findTripsByUser(user);

… est remplacĂ©e par

protected List<Trip> tripsByUser(User user) {
   return TripDAO.findTripsByUser(user);
}
tripList = tripsByUser(user);

L’ensemble constituĂ© par ces mĂ©thodes protĂ©gĂ©es est appelĂ©e thin layer. Il s’agit de la fine couche d’interface entre votre code et ses dĂ©pendances.
L’isoler de cette manière vous permet de tester l’ensemble de votre legacy code (voir le rĂ©sultat obtenu Ă  cette Ă©tape, au niveau du tag thin-layer).  

En revanche, ce n’est pas une fin en soi. Sa prĂ©sence n’a pour but que de vous permettre de tester votre code. 
C’est la seule raison pour laquelle la visibilitĂ© protected est acceptable. Il vous faut donc nĂ©cessairement aller plus loin.

Note: Nous en profitons pour vous rappeler que vous ne devriez jamais changer la visibilitĂ© d’un Ă©lĂ©ment (classe, mĂ©thode, etc.) dans l’unique but de le tester.

Explicitation des dépendances 

Si nous nous sommes donnĂ© tant de mal Ă  tester notre legacy code, c’est que nous souhaitons l’amĂ©liorer.
Pour rappel, voici sa forme actuelle. 

public class TripService {

   public List<Trip> getTripsByUser(User user) throws UserNotLoggedInException {
      List<Trip> tripList = new ArrayList<Trip>();
      User loggedUser = getLoggedUser();
      boolean isFriend = false;
      if (loggedUser != null) {
         for (User friend : user.getFriends()) {
            if (friend.equals(loggedUser)) {
               isFriend = true;
               break;
            }
         }
         if (isFriend) {
            tripList = tripsByUser(user);
         }
         return tripList;
      } else {
         throw new UserNotLoggedInException();
      }
   }

   protected List<Trip> tripsByUser(User user) {
      return TripDAO.findTripsByUser(user);
   }

   protected User getLoggedUser() {
      return UserSession.getInstance().getLoggedUser();
   }

}

Nous allons nous concentrer sur nos dĂ©pendances qui, bien qu’Ă©tant maintenant simulables, restent fortement couplĂ©es Ă  notre code. 
Pire, elles ne sont pas explicites. Autrement dit, si l’on souhaite crĂ©er ce service, nous n’avons pas connaissance de ses dĂ©pendances et il est impossible de lui fournir. 

new TripService(); // No dependency expected

D’autre part, cela introduit une responsabilitĂ© qui ne lui est pas inhĂ©rente (voir Single Responsibility Principle). Ce service traite de voyages et ne devrait en aucun cas savoir comment rĂ©cupĂ©rer la session courante. 
C’est un anti-pattern extrĂŞmement courant qui rĂ©duit considĂ©rablement la testabilitĂ© du code.

De ce fait, notre nouveau but est maintenant d’expliciter ces deux dĂ©pendances. 

Explicitation paramétrique

Commençons par la dépendance vers la classe UserSession :

UserSession.getInstance().getLoggedUser()

Cette dernière ne sert qu’Ă  rĂ©cupĂ©rer l’utilisateur connectĂ© dans une seule et unique mĂ©thode.
On devine donc que l’on peut lui passer directement. Il nous faut donc en changer la signature. Pour minimiser les risques, faisons-le Ă  travers notre IDE.

Note : Nous entrons ici dans une phase de  refactoring  qui comporte un lĂ©ger risque puisque l’on modifie la signature d’une mĂ©thode.
Certes, notre IDE nous y aide en modifiant tous les appels Ă  cette dernière, mais cela n’est pas suffisant.
Il faut avoir une vue complète de ces derniers pour valider par la suite que la bonne valeur est transmise. La quantitĂ© d’appels Ă  modifier est un bon indicateur du risque pris. Afin de le minimiser, nous vous conseillons de mettre un espace comme valeur par dĂ©faut du paramètre, afin de gĂ©nĂ©rer une erreur syntaxique qui sera nĂ©cessairement dĂ©tectĂ©e Ă  la compilation. Ainsi, vous serez obligĂ© de valider les appels modifiĂ©s.

Notre méthode devient donc : 

public List<Trip> getTripsByUser(User user, User loggedInUser) throws UserNotLoggedInException

Après avoir mis à jour ses appels (dans notre cas, cantonnés à nos TU) et vérifié que les tests passent toujours au vert, nous pouvons modifier notre méthode pour faire usage du nouveau paramètre :

public List<Trip> getTripsByUser(User user, User loggedInUser) throws UserNotLoggedInException {
   List<Trip> tripList = new ArrayList<Trip>();
   boolean isFriend = false;
   if (loggedInUser != null) {
      for (User friend : user.getFriends()) {
         if (friend.equals(loggedInUser)) {
            isFriend = true;
            break;
         }
      }
      if (isFriend) {
         tripList = tripsByUser(user);
      }
      return tripList;
   } else {
      throw new UserNotLoggedInException();
   }
}

Si les tests passent toujours, la méthode de la thin layer peut être supprimée.

Explicitation par constructeur

Reste alors l’autre dĂ©pendance vers TripDAO. 

TripDAO.findTripsByUser(user)

Un premier problème est ici visible : il s’agit d’un appel statique direct. Dès lors, si l’on explicite notre dĂ©pendance pour obtenir une instance de classe, nous n’aurons toujours que la possibilitĂ© de faire cet appel.
Il nous faudrait donc enlever le caractère statique de cette méthode. Pour le faire de manière sécurisée, il faut :

  • s’assurer que cette mĂ©thode est bien testĂ©e ;
  • crĂ©er une mĂ©thode d’instance qui fait appel Ă  la mĂ©thode statique Ă  remplacer et la tester Ă©galement.
public List<Trip> tripsOf(User user) {
   return TripDAO.findTripsByUser(user);
}

Cela permet de migrer un Ă  un les appels. Une fois la migration vers la mĂ©thode d’instance terminĂ©e, la mĂ©thode statique peut ĂŞtre supprimĂ©e.
Mais avant cela, il nous faut nous attaquer Ă  l’explicitation de notre dĂ©pendance. Il nous faut fournir celle-ci lors de la construction du service.

Note : Nous vous passons les détails quant à la marche à suivre pour le faire de manière sécurisée ; la vidéo de Sandro Mancuso le détaille parfaitement.

Au final, la dépendance est explicitée dans le constructeur de la classe :

public class TripService {

    private final TripDAO tripDAO;

    public TripService(TripDAO tripDAO) {
        this.tripDAO = tripDAO;
    }
}

Et notre mĂ©thode ne fait plus usage de l’appel statique :

public List<Trip> getTripsByUser(User user, User loggedInUser) throws UserNotLoggedInException {
    List<Trip> tripList = new ArrayList<Trip>();
    boolean isFriend = false;
    if (loggedInUser != null) {
        for (User friend : user.getFriends()) {
            if (friend.equals(loggedInUser)) {
                isFriend = true;
                break;
            }
        }
        if (isFriend) {
            tripList = tripDAO.tripsOf(user);
        }
        return tripList;
    } else {
        throw new UserNotLoggedInException();
    }
}

Le résultat final est accessible par le tag HEAD.

Note : Le code obtenu Ă  cet instant n’est bien sĂ»r pas optimal car lĂ  n’Ă©tait pas l’objectif de cet article.
Vous pouvez consulter la vidéo de résolution du kata ou bien la branche java-solution pour avoir une idée de ce qui peut être obtenu. 

Conclusion

Par cet article, nous vous avons montré comment vous défaire de vos dépendances statiques de manière sécurisée.
Nous avons d’abord vu comment isoler une thin layer vous permettant ainsi de tester l’ensemble de votre legacy code.

Nous avons ensuite vu comment expliciter vos dĂ©pendances, que ce soit au travers d’un paramètre ou d’une instance de classe. 
Votre service :

  • est dorĂ©navant clair pour quiconque veut l’utiliser ; plus de mauvaises surprises !
  • permet d’injecter des implĂ©mentations alternatives si nĂ©cessaire; sa testabilitĂ© n’en est que renforcĂ©e.

Si vous souhaitez creuser ce sujet plus en détails, nous vous recommandons ce guide produit par Google.

Enfin, sachez que l’isolation de la thin layer est Ă©galement applicable Ă  la crĂ©ation d’objets ou Ă  des appels de mĂ©thodes finales, l’article ayant pour sa part couvert les appels statiques. 

Catégories: Blog Société

Rex - AngularJS et les Fuites mémoires

Zenika - jeu, 01/22/2015 - 20:55

Il y a peu, j'ai eu le privilège de travailler sur un très gros projet AngularJS. Et par très gros j'entends : dĂ©mesurĂ©, du genre qui pousse le framework dans ses derniers retranchements. Un projet oĂą la limite « officielle Â» du nombre de 2000 bindings pour obtenir des performances acceptables (pour les versions <1.3 du moins) se compare avec les 70 000 bindings d'une seule page comportant 1Go de donnĂ©es.

Les fuites mĂ©moires, sont dĂ©jĂ  des phĂ©nomènes difficiles Ă  rĂ©soudre, mais dans un tel contexte, cela devient un vĂ©ritable cauchemar ! Voici donc un retour d'expĂ©rience sur la chasse aux fuites mĂ©moires sur un projet AngularJS.

La littérature évoque généralement deux approches : La méthode "Généticienne" : A base de relecture de code Effectivement, l'ADN de votre appli contient probablement des anomalies répertoriées (fuites mémoires ou non). L'idée n'est pas nécessairement de repasser sur tout le code mais de se focaliser sur certaines instructions ou patterns clés... Read Rex - AngularJS et les Fuites mémoires

Catégories: Blog Société

Revue de Presse Xebia

Revue de Presse Xebia
La revue de presse hebdomadaire des technologies Big Data, Cloud et Web, architectures Java et mobilité dans des environnements agiles, proposée par Xebia.

 

Agilité If it needs to happen: Schedule it! http://www.gravatar.com/f23d9dee080a22a6bb65caad9997acedhttp://blog.xebia.fr/author/lperothttp://twitter.com/LudovicPEROTPar Ludovic Perot

Le blog de Mike Cohn est souvent de qualitĂ©. Il a invitĂ© Lisa Crispin pour Ă©crire le prĂ©sent billet. Vous vous dites qu’Ă  la vue du titre, Lisa va enfoncer une porte ouverte : il faut prendre le temps de planifier un travail qui doit se rĂ©aliser.

Pourtant, au travers d’une anecdote qui peut faire Ă©cho Ă  des situations que vous rencontrez rĂ©gulièrement, le billet touche des sujets plus profonds : ils vous donnent quelques arguments sur le bien-fondĂ© du binomage, du point quotidien, du recours au backlog pour faire les choses. Et cette anecdote se fait de manière rĂ©aliste, puisque l’Ă©quipe dont elle parle est distribuĂ©e (comme 61% des Ă©quipes agiles, selon Scott Ambler) !

Xavier blogue un peu …: Scrum : quel est le rĂ´le le plus important ? http://www.gravatar.com/f23d9dee080a22a6bb65caad9997acedhttp://blog.xebia.fr/author/lperothttp://twitter.com/LudovicPEROTPar Ludovic Perot

Xavier Nopre nous partage ses rĂ©flexions sur l’importance de chacun des rĂ´les Scrum.

Mettre au mĂŞme niveau Scrum Master, Product Owner et Ă©quipier fait sens. Scrum met naturellement en avant l’importance des Ă©quipiers mais cela peut s’effacer dans bon nombre d’implĂ©mentation du framework.

Ce billet est un bon rappel des fondamentaux pour chaque rĂ´le. Et il est toujours bon de revenir de temps en temps Ă  la base !

La monnaie de l’attention par In Principo http://www.gravatar.com/6beb8800b1d5d45c22ecc81062e12448http://blog.xebia.fr/author/nlochethttp://twitter.com/nicolaslochetPar Nicolas Lochet

La bonne organisation des réunions reste un problème récurrent en entreprise.

Leur multiplication et le temps qu’elles occupent sont devenus la plaie des managers. Il n’est pas facile d’y remettre du sens, d’y redĂ©ployer l’Ă©coute et le partage. Autrement dit, de s’assurer qu’avec une bonne attention, la rĂ©union soit efficace.

Cet article vous propose une technique d’animation de rĂ©union qui, malgrĂ© quelques limites (d’ailleurs exposĂ©es dans l’article), peut facilement remettre l’attention au coeur de vos rĂ©unions.
Ă€ tester d’urgence!

L’agilitĂ© coute-t-elle plus cher ? http://www.gravatar.com/446d657538e086173eac4467a91c9d86http://blog.xebia.fr/author/omarquethttp://twitter.com/%40omarquetPar Olivier Marquet

L’agilité coûte-t-elle plus cher qu’une approche waterfall ? Alexandre Boutin nous partage sa réflexion sur le coût perçu de l’agilité.

L’agilité implique l’adaptation au changement et le droit à l’erreur, rétrospectivement cela peut être considéré par certains comme une perte de temps et donc d’argent.

Adapter son besoin aux retours clients à un coût, suivre un plan prédéfini en ligne droite en à un autre mais il ne faut pas oublié la valeur créée pour le client qui dans le premier cas sera plus importante.

Front Sortie de TypeScript 1.4 http://www.gravatar.com/8847b14eee72162957c0f4c0d462b8eehttp://blog.xebia.fr/author/blemoinehttp://twitter.com/benoit_lemoinehttp://github.com/mbretonPar Benoit Lemoine

TypeScript, le langage fournissant un typage statique à JavaScript, sort cette semaine en version 1.4 . Cette version contient de nombreuses nouveautés, parmi lesquels on pourra citer :

  • le type union, permettant d’indiquer qu’une valeur est « d’un type ou d’un autre » ;
  • la possibilitĂ© de dĂ©finir des alias de type avec le mot clef type
  • le support des mots clefs let et const, provenant directement d’EcmaScript 6
  • le support de l’interpolation de chaĂ®ne de caractère, provenant aussi d’ES6,  `une chaine avec une $variable`

TypeScript n’en finit donc pas de s’amĂ©liorer et vise pour les prochaines versions Ă  amĂ©liorer encore le support d’ES6.

Back Cloud, DevOps, BigData seront les tendances 2015 http://www.gravatar.com/b48c1ee560ff6432a574dceb746dff79http://blog.xebia.fr/author/romain-niveau%2Fhttp://twitter.com/RomainNVhttp://github.com/rniveauPar Romain Niveau

Comme chaque annĂ©e, des articles essayent de prĂ©voir quelles seront les tendances de l’annĂ©e Ă  venir dans diffĂ©rents domaines.

L’IT n’Ă©chappe pas Ă  ce phĂ©nomène et cet article essaye de dĂ©crire les tendances pour l’annĂ©e en cours.

Deux choses sont Ă  remarquer. Les tendances dĂ©jĂ  visible en 2014 vont prendre encore plus d’ampleur avec le dĂ©veloppement du cloud, des big data et du mouvement devOps.

Le deuxième point est la sĂ©curitĂ©. Après les bugs majeures HeartBleed et ShellShock, l’attention sera particulièrement portĂ©e sur la sĂ©curitĂ©, surtout dans le domaine du cloud.

Java 9 ne suffit pas, parlons de Java 10 http://www.gravatar.com/b48c1ee560ff6432a574dceb746dff79http://blog.xebia.fr/author/romain-niveau%2Fhttp://twitter.com/RomainNVhttp://github.com/rniveauPar Romain Niveau

Dans cet interview, deux gourous d’Oracle (Brian Goetz et John Rose) nous parlent un peu plus du futur de Java.

Bien entendu ils reviennent sur Java 9, la prochaine release majeure de Java mais ils nous parlent Ă©galement de Java 10 avec les collections primitives (List<int>) ou encore les indices de tableaux en format long.

Ils discutent également des projets Panama et Valhalla qui seront très importants pour le futur de Java.

 

Le coin de l’Alliance Thiga http://twitter.com/innothigaPar Simon Joliveau

Très habituĂ©s Ă  la richesse fonctionnelle de leurs smartphones, les utilisateurs commencent Ă  avoir le mĂŞme niveau d’exigence vis-Ă -vis des gadgets connectĂ©s. A l’image des enceintes connectĂ©es de l’entreprise Sonos, le matĂ©riel doit aujourd’hui savoir Ă©voluer au rythme des mises Ă  jour logicielles, intĂ©grer de nouvelles fonctionnalitĂ©s et s’intĂ©grer dans un large Ă©cosystème ; bref, devenir de vĂ©ritables plateformes Ă©volutives. Cet article est un Ă©cho intĂ©ressant Ă  des projets lancĂ©s par des grands acteurs français et qui visent Ă  crĂ©er des plateformes d’intermĂ©diation entre objets connectĂ©s. A lire !

Catégories: Blog Société

Piloter une tâche asynchrone Java/Groovy depuis un composant WebView JavaFX avec JavaScript

odelia technologies - mer, 01/21/2015 - 19:07

Le composant JavaFX WebView réunit deux mondes : celui de Java et d'HTML5, et offre une interaction Java/JavaScript à double sens. D'une part, il est possible d'exécuter du code JavaScript dans le contexte de la page web chargée par le composant WebView, et d'autre part, on peut exécuter du code Java présent dans l'application JavaFX à partir du code JavaScript (voir la documentation de la classe WebEngine).

Dans ce dernier cas, plus précisément, lorsque l'on appelle une méthode sur la référence de l'objet Java passé au travers d'une propriété de l'objet JavaScript window, l'appel est synchrone.
Cependant, il pourrait être intéressant de pouvoir déclencher un traitement asynchrone côté Java, depuis du code JavaScript de la page web, et recevoir le résultat de ce traitement une fois celui-ci terminé.

C'est ce que je vais démontrer dans le reste de cet article, en utilisant GroovyFX pour créer l'application JavaFX sous la forme d'un script Groovy. Pour la partie web, qui consiste en un fichier .html chargé dans un composant JavaFX WebView, je recours à AngularJS et son service $q qui implémente les promises. Il serait tout à fait possible d'utiliser jQuery et son implémentation des promises à la place.

L'idée principale est celle-ci : à partir du code JavaScript, appeler une méthode d'objet Java et lui transmettant l'objet JavaScript deferred créé via le service $q. Dans l'implémentation de la méthode Java (ou Groovy), un objet de type Task est créé puis démarré pour réaliser le traitement asynchrone ; selon l'issu traitement, on appelle resolve ou reject sur l'objet deferred, ce qui fait que le code JavaScript de la page web n'est pas bloqué et peut réagir en fonction de la réalisation de la promesse.
Voici le script GroovyFX AngularFX.groovy (disponible en fichier joint) qui, exécuté via une commande groovy, permet de démarrer l'application JavaFX comprenant un composant WebView :

@Grab('org.codehaus.groovyfx:groovyfx:0.4.0')
import static groovyx.javafx.GroovyFX.start

import javafx.beans.value.ChangeListener
import javafx.event.EventHandler
import static javafx.concurrent.Worker.State.*
import javafx.concurrent.Task


class ProcessTask extends Task {
    def expression

    ProcessTask(expression) {
        this.expression = expression
    }

    @Override protected String call() throws Exception {
        Eval.me(this.expression)
    }
}

class FX {
    def process(expression, deferred) {
        def task = new ProcessTask(expression)

        task.messageProperty().addListener( { s, o, n ->
            println n.value
        } as ChangeListener)

        task.onSucceeded = { event ->
            deferred?.call('resolve', task.value) 
        } as EventHandler

        task.onFailed = { event ->
            deferred?.call('reject', task.exception.message) 
        } as EventHandler        
     
        new Thread(task).start()
    }
}

start {
    stage(title: 'AngularFX', visible: true) {
        scene(width: 800, height: 600) {            
            borderPane  {
                vbox {
                    webView = webView()
                }                  
            } 
        }
    }

    webView.engine.loadWorker.stateProperty().addListener({ t, o, n ->
        if (n == SUCCEEDED) {
            webView.engine.executeScript("window").setMember("FX", new FX())
        }
    } as ChangeListener)

    webView.engine.onError = { event ->
        println 'error: ' + event.message
    } as EventHandler

    // Capture alerts
    webView.engine.onAlert = { event ->
        println 'alert: ' + event.data.toString()
    } as EventHandler

    webView.engine.load("file:///${System.getProperty('user.dir')}/angularfx.html")
}

Le code est relativement simple : tout d'abord, on charge la page web angularfx.html supposée se trouver dans le même répertoire que le script. Lorsque le page est complétement chargée, on injecte la propriété FX dans l'objet JavaScript window avec une référence vers un objet de type FX. Cette classe comprend une seule méthode, process, qui sera invoquée depuis du code JavaScript de la page angularfx.html. La méthode process a la responsabilité de créer la tâche -une instance de ProcessTask héritant de la classe JavaFX Task- dont l'exécution se fera dans un thread séparé, mais également, en fonction du résultat du traitement, de satisfaire et de rejeter la promesse (appel à resolve ou reject sur l'objet deferred JavaScript).

Notez qu'à titre d'exemple, la tâche asynchrone se contente d'évaluer le code Groovy qu'on lui transmet dans son constructeur, dans la méthode call. En cas de réussite, on appelle resolve sur l'objet deferred en transmettant le résultat de l'évaluation ; en cas d'échec, c'est reject qui est appelé sur l'objet deferred, en passant le message de l'exception à l'origine de l'échec (méthode process de la classe FX).

La page web angularfx.html comprend une application AngularJS permettant l'évaluation (asynchrone) de code Groovy saisi dans une zone d'édition, et d'en afficher le résultat dans la page web.

Voici le code source d'angularfx.html (Ă©galement disponible en fichier joint) :



    
        
        
            Evaluate
        
        Evaluate 
        

        
        
            angular.module('angularFX', [])
                .controller('MainCtrl', function($q) {
                    var self = this;

                    self.process = function() {
                        var deferred = $q.defer();
                        deferred.promise.then(
                            // success
                            function (response) {
                                self.message = response
                            },
                            // failure
                            function (response) {
                                // can be something else                             
                                self.message = response
                            }
                        );                 
                        FX.process(self.expression, deferred);
                    };                    
                });
        
    

Un click sur le bouton Evaluate déclenche l'exécution de la méthode process du contrôleur MainCtrl. Cette méthode crée un objet deferred au moyen du service injecté $q d'AngularJS, puis définit par deux fonctions JavaScript, se qui va se passer en cas de succès et d'échec (appel deferred.promise.then()) : dans notre exemple, on se contente d'affecter la propriété message du contrôleur avec le résultat de l'évaluation opéré côté Java ou avec un message d'exception. La valeur de message sera automatiquement affichée dans l'élément h2 de la page du fait de la liaison sur la propriété ctrl.message.

Le fait de pouvoir invoquer du code Java/Groovy, qu'il soit asynchrone ou non, depuis un composant WebView placé dans une scène JavaFX, ouvre des perspectives intéressantes. C'est un peu comme être dans une application hybride dans laquelle on peut combiner la puissance et l'étendue du langage Java avec la souplesse de JavaScript au sein d'une présentation HTML5.

Nul doute pour moi de continuer à explorer une telle combinaison... en allant par exemple plus loin avec cette idée d'évaluation de code Groovy.

Fichier(s) attachĂ©(s):  AngularFX.groovy angularfx.html
Catégories: Blog Société

Golo : les slides et les sources de la présentation

Alpes JUG - mer, 01/21/2015 - 17:44

Si la prĂ©sentation vous a plu et que vous souhaitez jouer un peu avec les exemples, ou si vous n’avez pas pu venir, vous serez certainement content de retrouver les slides et les sources de la prĂ©sentation :

Catégories: Association

GDG DevFest 2015 filmé et voté

Xebia s’associe au GDG DevFest 2015, le vendredi 30 janvier et se tiendra Ă  l’ECE Paris, 10 rue Sextius Michel, 75015 Paris.
1 journée, plus de 300 participants et plus de 20 heures de pure technologie Google avec 4 tracks en parallèle !

 

La chaine XebiaTV filmera

Pour cette occasion, notre chaîne XebiaTV apporte sa caméra dans les locaux et filmera toute la journée une track du DevFest 2015.

Vous pourrez alors voir et revoir ces conférences sur notre chaîne post salon :

  • La keynote d’ouverture par Alexis Moussine-Pouchkine
  • 11h15 – 12h : Docker in the cloud with diamonds, par David Gageot
  • 13h30 – 14h15 : From Docker to Kubernetes: a developer’s guide to containers, par Mandy Waite, Google
  • 14h30 – 15h15 : No one at Google uses MapReduce anymore – Cloud Dataflow and the FlumeJava paper explained, par Martin Görner, Google
  • 16h – 16h45 : Boost your App Engine app using Managed VMs technology, par Marco Tranquillin, Revevol Italia
Les participants voteront

Après Devoxx France et Devoxx UK, nos voting boards seront présents au DevFest 2015. Disposés à chaque sortie de salle, vous pourrez voter pour chaque conférence. Les votes seront alors récupérés puis publiés post-salon.

Espérant vous y voir nombreux !

Catégories: Blog Société

Zero downtime deployment avec Node.js et Express, une première étape …

Lorsqu’on souhaite stopper ou redémarrer un serveur, différentes solutions s’offrent à nous. Parmi elles, la possibilité d’envoyer un signal de type SIGTERM au processus.

Cette solution est couramment utilisée, malheureusement cela entraîne la coupure des connexions en cours sans permettre au serveur d’honorer les requêtes en cours de traitement.

Dans l’objectif de fournir une meilleure qualité de service, il est important d’honorer toute requête entrante. Comment faire, donc, pour permettre le redémarrage d’un serveur en douceur, sans couper brutalement les connexions en cours ?

Le protocole HTTP permet au serveur de répondre aux requêtes entrantes par un status code 503 qui signifie que le service n’est pas disponible (Service Unavailable). L’idée est donc de renvoyer ce status code dès lors que le process a reçu un signal SIGTERM, tout en laissant le temps au serveur de terminer le traitement des requêtes HTTP en cours, puis de stopper le serveur une fois que les requêtes en cours sont traitées. Il est toujours possible de killer le process du serveur si cela met trop longtemps.

Node.js

Avec Node.js, il est possible d’écouter les signaux reçus par le système et d’y réagir. Il est donc possible de mettre en place une mécanique qui instruit le serveur de répondre aux nouvelles requêtes entrantes par un status code 503, puis de couper le serveur une fois les requêtes en cours traitées.

Cela donne le code suivant:

var start = new Date();
var app = express();
var gracefullyClosing = false;

app.configure(function() {
  app.set('port', process.env.PORT || 8000);

  app.use(function(req, res, next) {
    if (!gracefullyClosing) {
      next();
      return;
    }

    res.setHeader("Connection", "close");

    res.send(503, "Le serveur est en cours de redémarrage.");
  });

  app.use(app.router);
});

app.get('/', function(req, res) {
  res.send(200, 'OK');
});

httpServer = app.listen(app.get('port'));

process.on('SIGTERM', function() {
  logger.info("RĂ©ception d'un signal SIGTERM. Tentative de fermeture gracieuse des connexions.");

  gracefullyClosing = true;

  httpServer.close(function() {
    logger.info("Fermeture des connexions existantes.");
    process.exit();
  });

  return setTimeout(function() {
    console.error("Fermeture forcée des connexions: Les connexions n'ont pas pu être fermées dans les temps.");
    process.exit(1);
  }, 30 * 1000);
});

L’appel de la fonction close sur l’instance de serveur HTTP renvoyée Express, permet au serveur de terminer le traitement des requêtes en cours avant de s’arrêter.

Si votre application Node.js est correctement redondée avec un reverse proxy (Nginx, HAProxy) devant les différentes instances, les requêtes entrantes seront redirigées vers d’autres instances en état de traiter les requêtes. Cela sera le cas dès lors que votre application répondra aux requêtes entrantes avec des status code 502 ou 503 par exemple.

Nginx

Si votre application est déployée derrière un reverse proxy tel que Nginx, il suffit de configurer celui-ci avec plusieurs flux upstream vers différentes instances de votre application pour qu’il soit capable de passer la main à une autre instance lorsqu’il reçoit un code erreur 502 ou 503 en réponse à une requête transmise à une des instances.

upstream my_app_upstream {
    server 127.0.0.1:7000;
    server 127.0.0.1:8000;
    server 127.0.0.1:9000;
}

Ensuite, il faut déclarer ce que Nginx doit faire lorsqu’il reçoit une réponse 502 ou 503 et le tour est joué. Ici, nous indiquons à Nginx via la directive proxy_next_upstream de faire suivre la requête au prochain flux upstream lorsqu’il reçoit en réponse une erreur, un timeout ou bien un code HTTP 502 ou 503:
location /app {
 ...
 proxy_next_upstream error timeout http_502 http_503;
 ...
 proxy_pass http://my_app_upstream;
}

Limitations

Ce fonctionnement décrit dans cet article répond bien aux besoins d’applications traitant des requêtes HTTP simples, néanmoins il ne répond pas au problème des configurations qui ont activé l’option de keepalive pour les connexions HTTP, ni aux applications utilisant les websockets. Il faudra dès lors trouver une solutions adaptée.

Conclusion

La mise en oeuvre de la notion de Graceful Shutdown lors d’un redémarrage pour raison de déploiement d’une nouvelle version, est une première étape importante pour arriver à faire du Zero Downtime Deployment. Cela permet, non seulement d’honorer les requêtes en cours de traitement, mais également à vos reverse proxy de prendre connaissance de l’absence de service et redispatcher les requêtes sur d’autres serveurs avant que le flux upstream ne soit coupé.

Pour approfondir

Cet article, directement inspirĂ© d’une sĂ©rie d’articles sur la notion de Zero Downtime Deployment (Voir les liens mentionnĂ©s suivants), sera suivi d’un prochain article dans la mĂŞme lignĂ©e expliquant la mise en oeuvre de la clusterisation d’une application Node.js.

Si vous souhaitez en apprendre plus sur le sujet, vous pouvez vous référer aux articles suivants très bien écrits: 

Catégories: Blog Société

Présent et avenir du monitoring de flux

Avoir un monitoring de flux performant est critique : intĂ©grant tous les flux de donnĂ©es il est Ă  mĂŞme d’offrir une vision synthĂ©tique de tout le système d’information.

L’objectif de cet article est de vous permettre de comparer votre système actuel avec les bonnes pratiques gĂ©nĂ©ralement observĂ©es et de vous donner des pistes d’Ă©volution.

Monitoring de flux ?

On appelle un flux un ensemble d’appels de services et/ou d’envois de messages qui ensemble forment un service mĂ©tier. Dans un système d’information complexe, un tel flux traverse souvent plusieurs applications et utilise parfois plusieurs technologies : par exemple un utilisateur clique sur un Ă©cran qui dĂ©clenche un appel REST qui provoque une invocation SOAP dont le traitement envoie une sĂ©rie de messages JMS.

Monitorer ces flux signifie donc mettre en place un monitoring des activitĂ©s mĂ©tier (Business Activity Monitoring). Cela consiste Ă  collecter des donnĂ©es dans toutes les couches applicatives pour les corrĂ©ler. Cela permet d’obtenir une vision transverse agrĂ©gĂ©e de l’activitĂ© de votre système d’information. Ce monitoring doit fournir Ă  tout moment l’Ă©tat de santĂ© et la performance des fonctions mĂ©tiers importantes (Key Performance Indicator). Dans le passĂ© ces informations Ă©taient souvent calculĂ©es sĂ©parĂ©ment pour chaque couche technique.

Le monitoring de flux ne remplace pas le monitoring de composants mais le complète de la mĂŞme manière que les tests d’intĂ©gration complètent les tests unitaires. Chaque brique doit ĂŞtre surveillĂ©e isolĂ©ment d’une manière technique pour identifier les problèmes qui lui sont propres, alors que le monitoring de flux va s’intĂ©resser aux Ă©lĂ©ments transverses et mĂ©tier qui nĂ©cessitent une vision globale du système. Il y a un bien une zone de recouvrement entre les deux mais il ne faut pas les confondre ou utiliser l’un pour remplacer l’autre.

Dans la suite de l’article un message mĂ©tier signifiera indiffĂ©remment le contenu d’un appel de service ou d’un message envoyĂ©.

Pour avoir un bon monitoring de flux Fonctionnalités

La fonctionnalitĂ© essentielle est d’ĂŞtre capable d’identifier les flux mĂ©tier dans les messages atomiques. GĂ©nĂ©ralement cela passe par l’utilisation d’un identifiant unique (correlation id). Tous les messages d’un mĂŞme flux devront donc contenir le mĂŞme identifiant. Cela passe par la mise en place d’une brique spĂ©cifique dans les diffĂ©rents applicatifs chargĂ©e de gĂ©nĂ©rer l’identifiant en dĂ©but de chaĂ®ne et de le propager dans les traitements. Cette brique sera aussi responsable de transmettre une copie des messages pour qu’elle soit intĂ©grĂ©e dans le monitoring.

Corrélation

Le système doit ĂŞtre capable de prendre en compte des Ă©vènements hĂ©tĂ©rogènes : si les messages envoyĂ©s par les diffĂ©rents composants comportent des Ă©lĂ©ments communs (horodatage par exemple) ils comportent aussi des informations spĂ©cifiques liĂ©es au mĂ©tier du service (nom du service mĂ©tier, identifiant d’objets). ĂŠtre capable d’intĂ©grer facilement ces diffĂ©rentes donnĂ©es permettra de construire au plus juste des mĂ©triques fonctionnelles qui Ă©volueront en mĂŞme temps que les services.

Pour pouvoir exploiter au mieux ces donnĂ©es, il faut disposer d’un système de dashboarding configurable : il ne s’agit pas seulement de prĂ©dĂ©finir un ensemble d’Ă©crans de monitoring fixes, mais aussi de pouvoir s’en servir pour des Ă©tudes ou des investigations. Les systèmes de monitoring utilisĂ©s habituellement sont souvent mal adaptĂ©s Ă  ce type d’usage: leur ergonomie « Ă  l’ancienne » rend l’exploration de donnĂ©es pĂ©nible. Par ailleurs il s’agit beaucoup de solutions monolithiques intĂ©grant monitoring collecte et stockage de donnĂ©es.

La base de donnĂ©es doit fournir des fonctionnalitĂ©s d’indexation avec une couverture maximum, l’idĂ©al Ă©tant d’indexer l’intĂ©gralitĂ© des champs des donnĂ©es. Cela permet de simplifier les investigations en cas d’erreur : on pourra par exemple identifier tous les messages qui concernent un certain numĂ©ro de compte. Pour des questions de volume, on pourra limiter l’indexation dans le temps (48 heures au moins), en gardant la possibilitĂ© de rĂ©indexer des messages passĂ©s.

Contraintes Ne jamais interférer avec le métier

Un échec dans la brique de monitoring ne doit jamais entrainer de conséquences sur le fonctionnel, il faut donc bien isoler techniquement les deux.

Ensuite le monitoring ne doit pas entrainer de baisse de performances, les messages de monitoring doivent ĂŞtre envoyĂ©s sous forme d’Ă©vènements asynchrones (pattern wiretap) Ă  l’aide d’un middleware de messages. Il est souhaitable d’avoir une infrastructure de message dĂ©diĂ©e, car on Ă©vite ainsi tout risque de surcharge.

Limiter les développements spécifiques

Enfin il faut limiter les développements métier dans les briques de monitoring : si de la configuration ou un peu de développement spécifique est inévitable, surtout pour les métriques les plus précises, il faut éviter de recoder des comportements fonctionnels. Le résultat est souvent fragile et va rendre plus difficile les évolutions du métier.

Briques logicielles nécessaires

Pour répondre à ces critères, on peut donc identifier les différentes briques qui sont nécessaires pour le monitoring de flux :

  • Les informations sont transmises sous forme d’Ă©vĂ©nements dans un middleware de message dĂ©diĂ©.
  • Un système de traitement de messages pour faire des agrĂ©gations et de la dĂ©tection d’Ă©vènements.
  • Une base de donnĂ©es indexĂ©e oĂą ils sont stockĂ©s.
  • Une console de monitoring pour les exploiter.

Présent

Pratiques actuelles

Votre système d’information comporte dĂ©jĂ  une partie des blocs techniques dont on a besoin, comme un système de messages ou une base de donnĂ©es. Malheureusement, les spĂ©cificitĂ©s du monitoring empĂŞchent souvent d’utiliser les mĂŞmes outils :

  • Du fait du grand nombre de messages entrant dans le système, les middlewares classiques n’offrent pas une capacitĂ© de traitement suffisante, il est donc nĂ©cessaire d’utiliser un système de communication spĂ©cialisĂ© pour ce type de volume : AMQP, SNMP, RSYSLOG, ZeroMQ.
  • Pour le traitement de messages, un système de CEP (complex event processing) comme Drool Fusion va gĂ©rer les aspects techniques. Il va conserver en mĂ©moire un Ă©tat du système sur lequel on dĂ©finit des règles dĂ©clenchant des traitements ou des alertes.
  • La base de donnĂ©es doit stocker des messages ayant des formats hĂ©tĂ©rogènes et qui Ă©voluent avec les applications. On s’orientera donc gĂ©nĂ©ralement vers une solution de stockage de type NoSQL permettant d’avoir des schĂ©mas de donnĂ©es dynamiques tout en fournissant partitionnement et scalabalitĂ© afin d’absorber le volume et le dĂ©bit de donnĂ©es entrant. Les fonctionnalitĂ©s d’indexation d’Elastic Search en font gĂ©nĂ©ralement un bon choix.
  • Pour le dashboarding Kibana est le produit de rĂ©fĂ©rence pour visualiser des donnĂ©es stockĂ©es dans Elastic Search : il permet de construire des Ă©crans riches de manière flexible.
Le futur

Ce type d’architecture reposant sur des briques standard est limitĂ© sur deux aspects, le premier est technique et le second fonctionnel.

Toujours plus de messages

La première limite est liĂ©e Ă  l’augmentation du nombre de messages Ă  traiter. Dans des systèmes basĂ©s sur les nouvelles architectures de micro-services et qui intègrent de nouveaux usages (applications mobiles, Internet des objets) le nombre de messages est dĂ©multipliĂ©. L’objectif du système de monitoring Ă©tant de continuer Ă  absorber l’intĂ©gralitĂ© des messages il doit voir ses capacitĂ©s augmenter dans les mĂŞmes proportions.

Cela entraine la mise en place de plusieurs solutions :

  • MĂŞme en choisissant un broker rapide, les solutions de middleware de messages classiques plafonnent Ă  quelques milliers de messages par seconde. Il faut alors se tourner vers des solutions «Fast Data» dont Kafka semble aujourd’hui devenir la solution de rĂ©fĂ©rence.
  • L’intĂ©gration de messages dans le système de stockage doit passer par une solution d’ « Event Streaming ». Les solutions envisageables sont par exemple Apache Storm ou Apache Spark Streaming.
  • Le stockage d’un tel volume de donnĂ©es sera rĂ©alisĂ© sur un système de stockage distribuĂ© comme une Apache Cassandra ou HDFS d’Hadoop. Le stockage dans Elastic Search pourra ĂŞtre conservĂ© pour des besoins de requĂŞtage rapide sur des donnĂ©es rĂ©centes.

Ce type d’architecture « big data » permettant de combiner plusieurs approches de traitement en conservant un stockage unifiĂ© porte le nom de DataLake.

Des analyses plus poussées

Après les moteurs de règles classiques, on commence Ă  se tourner vers des solutions d’analyse plus pointues permettant de mieux mesurer ce qui se passe mais aussi de mieux prĂ©voir. Dans cette optique, la composante mĂ©tier du monitoring prend de plus en plus de poids et la distinction avec la BI s’efface et nous sommes convaincus qu’on verra bientĂ´t des solutions d’online machine learning enrichir ces systèmes.

Futur

Conclusion

Nous espĂ©rons vous avoir convaincu de la valeur qu’apporte le monitoring de flux. Aujourd’hui il est essentiel pour des raisons d’exploitation, demain il vous apportera Ă©galement de la valeur mĂ©tier. La mise en place ce type de solution dans un système d’information est un chantier structurant mais qui s’appuie sur des composants ouverts et bien connus, il n’y donc aucune raison pour ne pas s’y mettre.

Catégories: Blog Société

Premier pas avec Polymer

L'actualité de Synbioz - mer, 01/21/2015 - 00:00

Polymer est un ensemble de bibliothèques permettant de créer des éléments et applications reposant sur le principe des « Web Components » que j’ai introduit dans mon précédent article Pour cette introduction nous allons nous concentrer sur la réalisation d’un composant simple, reproduisant celui réalisé dans l’article Web components, l’avenir du web …, ce qui nous permettra de nous concentrer sur les apports de Polymer.

Pour le définir en quelques mots, Polymer est un « framework » fournissant l’assistance nécessaire au développement d’éléments et applications pour les navigateurs. Actuellement le projet est un avant goût destiné aux développeurs pour l’expérimentation et n’est pas encore destiné à la production. Rien ne vous empêche de l’utiliser, mais il faut s’attendre à des changements majeurs dans les futures versions.

Lire la suite...

Catégories: Blog Société

Nous avons 10 ans !

Nous venons de fĂŞter nos 10 ans chez Xebia.

Nous avons célébré dignement cet anniversaire à la Salle Wagram où anciens collègues et Xebians actuels étaient invités pour partager ce grand moment de bonheur.

anniversaire-10ans-Xebia

10 ans c’est long et c’est court ! 10 ans d’une aventure passionnante ponctuée par des moments de travail intense et de grandes joies.

De l’installation dans nos premiers locaux à la Défense, le lancement de Xebia Studio, la création des sociétés de l’Alliance en passant par les voyages au ClubMed et notre récompense Great Place to Work en 2014, nous avons vécu des instants fabuleux !

Nous avons à cœur de bien faire notre travail et continuerons de le faire à l’avenir.

Notre mission, nos valeurs et nos principes restent inchangés depuis le premier jour car ils sont l’explication de notre singularité dont nous sommes si fiers.

Un grand merci à toutes celles et tous ceux qui ont contribué à cette aventure et continuent de le faire chaque jour.

couverture-livre-10ans.jpg

J’ai voulu remercier à ma manière tous ceux sans qui rien n’aurait été possible en relatant dans un livre, les leçons apprises :« Les recettes de cuisine entrepreneuriale ».

L’intention n’est pas de me mettre en avant mais de partager en toute transparence et en toute honnêteté les recettes de cuisine de notre société que nous pensons être un peu particulière.

Vous pouvez télécharger le livre ici ou en demander une copie gratuite à marketing@xebia.fr.

Ce livre est complètement libre de droits et nous serions flattés si, d’aventure, il servait à certains d’entre vous, quelque soit le contexte.

Bon anniversaire Xebia !

Luc Legardeur

Président

Catégories: Blog Société

Livre blanc « Enjeux et compétences de la transformation numérique » co-écrit par le CESAMES et THE OPEN GROUP

Architecture Forum France (Open Group) - mar, 01/20/2015 - 11:52

Il n’existe actuellement quasiment plus de frein à la technologie numérique, de nouveaux usages apparaissent tous les jours et la facilité d’accès au monde et aux autres permet de diffuser ces usages à une vitesse qui complique leur appréhension

Cet article Livre blanc « Enjeux et compĂ©tences de la transformation numĂ©rique » co-Ă©crit par le CESAMES et THE OPEN GROUP est apparu en premier sur The Open Group France.

Catégories: Association

Partagez la connaissance

Partagez BlogsdeDeveloppeurs.com sur les réseaux sociaux