Microservices avec @SenecaJS chez @Clever_Cloud - PART I

Les origines de cet articles

Pour cette annĂ©e 2017, j’ai dĂ©cidĂ© de me remettre Ă  l’IOT et en cherchant les plateformes opensource(s?) de gestion d’objets connectĂ©s, provisionning, 
 (en gros, un application web qui vous affiche la liste de vos objets connectĂ©s, les donnĂ©es associĂ©es, des graphiques temps rĂ©els, qui vous permet d’ajouter des objets, dans dĂ©couvrir, 
) je n’ai rien trouvĂ© qui me corresponde rĂ©ellement, qui soit facile Ă  utiliser, Ă  “coder” et Ă  hĂ©berger. Mon modĂšle c’est thingworx 
 Mais ce n’est pas opensource. Donc finalement, pourquoi ne pas faire ma propre plateforme? :stuck_out_tongue_winking_eye: Ok, c’est ambitieux, mais c’est bien d’avoir un “side project” avec un “vrai sujet” et c’est formateur. En effet, au cours de ma quĂȘte et de mes rĂ©flexions j’ai notamment dĂ©cidĂ© d’utiliser le concept de microservices qui me semble bien se prĂȘter Ă  mes besoins de construction d’une plateforme modulaire, Ă©volutive, 


👋 Vous pouvez lire la partie II ici: http://k33g.github.io/2017/01/15/MICROSERVICES-ON-CC2.html

Micro services?

Alors, cet article n’est pas un dossier sur les microservices, mais plutĂŽt le journal de mes expĂ©rimentations avec les microservices.

Pour une prĂ©sentation sympa je vous engage Ă  lire l’article paru dans Programmez paru en DĂ©cembre 2015, Ă©crit par 2 consultants de chez Xebia: Les nouvelles architectures logicielles.

Pour moi, rapidement, un microservice, c’est une fonction ou un ensemble de fonctions que j’appelle de mon programme principal, mais qui ne sont pas localisĂ©es au mĂȘme endroit que mon programme principal (eg: les microservices que j’utilise peuvent ĂȘtre hĂ©bergĂ©s sur diffĂ©rents serveurs et je vais les utiliser dans mon code comme si j’en disposais en local sans me prĂ©occuper de savoir oĂč ils sont). Un microservice est indĂ©pendant, ça a l’avantage de simplifier le travail en Ă©quipe sur un projet d’envergure, de faciliter le partage de fonctionnalitĂ©s avec d’autres projets 
 Sans parler des notions de haute dispo, scalabilitĂ©, 


Mais lisez donc l’article dont je vous parlais plus haut.

Mes 1ers microservices avec SenecaJS

J’ai une appĂ©tence pour le JavaScript, ce qui a donc influĂ© tout naturellement mes recherches et mon choix s’est portĂ© sur le projet SenectaJS. Cette vidĂ©o et une bonne introduction Ă  l’utilisation de SenecaJS: Michele Capra - Microservices in practice with Seneca.js.

Préparation du 1er microservice

Le mieux est de directement crĂ©er un projet sur GitHub car je m’en sers pour dĂ©ployer mes services. Donc une fois votre projet crĂ©Ă© et clonĂ© sur votre poste, dans votre projet crĂ©ez un fichier package.json:

# on imagine que votre projet GitHub s'appelle ping-service 🏓
cd ping-service
npm init -y
npm install seneca --save

Votre fichier package.json devrait ressembler Ă  minima Ă  ceci:

{
  "name": "ping-service",
  "main": "index.js",
  "scripts": {
    "start": "node index.js"
  },
  "dependencies": {
    "seneca": "^3.2.2"
  }
}

Ensuite (dans le répertoire /ping-service), créez un fichier index.js

const seneca = require('seneca')()
const os = require('os')

const port = process.env.PORT || 8082

function pingpong(options) {
  this.add({role: "sport", cmd: "ping"}, (message, reply) => {
    reply(null, {answer: "pong"})
  })
}

seneca
  .use(pingpong)
  .listen({
    host: '0.0.0.0',
    port: port
  })

console.info(`🌍 service is listening on ${port}`)

Vous pouvez dĂšs maintenant lancer votre formidable service:

node index.js # ou npm start

Et le tester dans votre navigateur en appelant http://localhost:8082/act?role=sport&cmd=ping et vous obtiendrez en réponse:

{"answer":"pong"}

Ce qui vaut bien une petite đŸ•ș de victoire.

Préparation du 2Úme microservice

LĂ , vous ĂȘtes chaud comme la braise, on ne s’arrĂȘte pas, vous m’en faites un deuxiĂšme. LĂ  aussi, il faudra crĂ©er un projet sur GitHub, et avec beaucoup d’imagination, appelons le pong-service:

const seneca = require('seneca')()
const os = require('os')

const port = process.env.PORT || 8081

function pingpong(options) {
  this.add({role: "sport", cmd: "pong"}, (message, reply) => {
    reply(null, {answer: "ping"})
  })
}

seneca
  .use(pingpong)
  .listen({
    host: '0.0.0.0',
    port: port
  })

console.info(`🌍 service is listening on ${port}`)

Si vous prenez le temps de le tester, vous obtiendrez:

{"answer":"ping"}

On héberge les 2 services chez @Clever_Cloud

PlutĂŽt que de tout faire en local, nous allons hĂ©berger nos services Ă  l’extĂ©rieur. J’ai choisi de faire ça chez @Clever_Cloud pour plusieurs raisons:

  • la simplicitĂ© d’utilisation pour le dĂ©ploiement et la maintenance (je suis un dev, je n’ai pas envie de perdre mon temps avec des solutions compliquĂ©es pour hĂ©berger mes applis)
  • la possibilitĂ© d’ajouter une base de donnĂ©es facilement
  • la gestion automatique des updates, des fixes des failles de sĂ©curitĂ©
  • l’autoscalabilitĂ© (je vous rappelle que je veux faire de l’IOT 
 et que je suis un dev)
  • “No-downtime deployment”, ce qui est plutĂŽt rare ou alors faut te le gĂ©rer toi-mĂȘme
  • le support utilisateurs fait par la core team (et en :fr: dans mon cas, mĂȘme si mon job actuel m’oblige Ă  pratiquer l’anglais presque tous les jours, c’est quand mĂȘme super agrĂ©able et reposant de pouvoir utiliser sa langue natale)
  • 


C’est parti

  • Alors, nos deux microservices sont sur GitHub
  • Pour les grosses faignasses vous pouvez les cloner par ici:
    • https://github.com/wey-yu/ping-service
    • https://github.com/wey-yu/pong-service
  • il vous faudra vous enregistrer chez @Clever_Cloud (il y a une offre dĂ©couverte gratuite)

Et maintenant on dit que vous avez un compte et que vous voulez déployer:

1- Créer une application:

  • clicker sur + Add an application
  • dans la liste Select your GitHub repository, sĂ©lectionner votre projet sur GitHub

2- Choisissez le type de l’application:

  • dans notre cas, ce sera NodeJS

3- Editez le type d’instance

  • Clicker sur EDIT

  • Choisir une instance de taille pico
  • Clicker sur NEXT

4- Donnez un nom Ă  votre service et crĂ©ez l’application

5- Ne pas ajouter d’Add-On

  • Pour cette partie nous n’avons pas besoin d’add-on

6- Les variables d’environnement

  • Par dĂ©faut il y a toujours une variable PORT Ă©gale Ă  8080
    • une application sur Clever doit toujours â€œĂ©couter” sur le port http 8080
    • le port http 8080 est mappĂ© sur le port 80
    • donc pour accĂ©der Ă  vos webapps de l’extĂ©rieur, vous utiliserez le port 80
    • donc ne changez rien
  • Clicker sur NEXT

7- La crĂ©ation de l’application commence

  • Une application Node chez Clever doit possĂ©der un fichier package.json indiquant comment dĂ©marrer

    "scripts": {
      "start": "node index.js"
    }
    
  • Remarque: "main": "index.js" peut suffire
  • maintenant patientez un peu


  • Vous pouvez ensuite suivre le dĂ©ploiement de votre microservice:

8- Donnez une url humainement lisible Ă  votre microservice

9- Testez votre microservice

10- Exercice

Vous avez vu, c’est ultra facile, faites donc la mĂȘme chose pour le 2Ăšme microservice (pong)

Nous avons donc maintenant 2 microservices hebergés

  • 🏓 ping: http://mypingservice.cleverapps.io/act?role=sport&cmd=ping
  • 🏓 et pong: http://mypongservice.cleverapps.io/act?role=sport&cmd=pong

Nous allons maintenant voir comment créer un client pour les utiliser.

Utilisons nos microservices

Sur votre poste en local (vous pourrez l’hĂ©berger plus tard si vous le souhaitez), crĂ©ez un nouveau projet Node, avec du Express:

npm init -y
npm install express --save
npm install body-parser --save
npm install seneca --save

Ensuite créez un fichier index.js:

const express = require("express");
const bodyParser = require("body-parser");
const seneca = require('seneca')

const port = process.env.PORT || 8080;

const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));

let clientPong = seneca().client({host:'mypongservice.cleverapps.io', port:80})
let clientPing = seneca().client({host:'mypingservice.cleverapps.io', port:80})

app.get('/service/ping', (req, res) => {
  clientPing.act({role: "sport", cmd: "ping"}, (err, item) => {
    res.send(item)
  })
});

app.get('/service/pong', (req, res) => {
  clientPong.act({role: "sport", cmd: "pong"}, (err, item) => {
    res.send(item)
  })
});

app.listen(port);
console.log(`🌍 Web Server is started - listening on ${port}`);

⚠ Remarque: il existe une intĂ©gration Express-Seneca, mais lĂ  j’ai fait au plus simple.

  • Lancez node index.js
  • ouvrez votre navigateur
    • essayez http://localhost:8080/service/ping
    • essayez http://localhost:8080/service/pong

👏 gĂ©nial, on a bien nos services distants utilisables (une petite đŸ•ș).

Maintenant ce qui serait bien, cs serait d’avoir un systĂšme de “service discovery” pour Ă©viter d’avoir Ă  renseigner les urls des microservices.

Mais ce sera pour un prochain article (j’ai encore quelques coup de tournevis à donner 😃)

blog comments powered by Disqus

Related posts