Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Les Cylons avaient écrit "le Plan" en Golo

Les Cylons avaient écrit "le Plan" en Golo

Comment faire une plateforme IOT à haute disponibilité avec Golo, Coap et Hazelcast - Présentation pour le JUG SummerCamp 2015

Philippe CHARRIERE

October 03, 2015
Tweet

More Decks by Philippe CHARRIERE

Other Decks in Programming

Transcript

  1. #JSC2015 @k33g_org #GOLOBSG Philippe Charrière | @k33g_org Resp. Communication Technique

    Centre de R&D Nicolas Bourbaki Golo dancer @TypeUnsafe Committer #gololang Team member
  2. #JSC2015 @k33g_org #GOLOBSG Golo? 1 langage dynamique pour la JVM

    à base d’Invokedynamic facile à utiliser facile à modifier & c’est un projet Eclipse
  3. #JSC2015 @k33g_org #GOLOBSG Golo? Léger 708 kb Golo <3 Java

    Golo est rapide dans un contexte dynamique #notroll & en environnement contraint
  4. #JSC2015 @k33g_org #GOLOBSG … donc Si vous avez besoin de:

    Java + dynamique + délais courts + mémoire (IOT) -> Golo
  5. #JSC2015 @k33g_org #GOLOBSG Un marché en expansion Connectivité accrue Facteurs

    techniques(perfs, taille, …) Diversité des “things”
  6. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1 basestar avec hybrid

    (calculs + puis messages) … raiders Monitoring : http (sparkJava) + redis (affichage des raiders) 1er POC
  7. #JSC2015 @k33g_org #GOLOBSG Mon “algo” de navigation très très simpliste:

    > ne pas se rentrer dedans > ne pas dépasser un périmètre … perfectible
  8. #JSC2015 @k33g_org #GOLOBSG Donc nous allons voir Le modèle objet

    de Golo Golo utilise Java (version “facile”) avec SparkJava Golo “augmente” Java avec Jedis … comment envoyer les messages ?
  9. #JSC2015 @k33g_org #GOLOBSG Modèle(s) objet simple et efficace, proche de

    celui de Go, composition plutôt que héritage (*), approche mixte objet / fonctionnelle
  10. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1 basestar avec hybrid

    (calculs + puis messages) broker messages raiders
  11. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1 basestar avec hybrid

    (calculs + client MQTT) broker MQTT (moquette) raiders (clients MQTT)
  12. #JSC2015 @k33g_org #GOLOBSG MQTT? Standard OASIS (v3.1.1) depuis 11/2014 Modèle

    événementiel “Content agnostic” Nombreuses implémentations paho = Standard Simple & Léger
  13. #JSC2015 @k33g_org #GOLOBSG MQTT? Broker de message Publisher Listener (Subscriber)

    Listen Event Publish Clients MQTT Publication de message sur un “topic” Souscription à des “topics” (wildcards possibles) Broker MQTT Routage / Distribution Rétention des messages Mode bridge possible Publish / Subscribe pattern
  14. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1b basestar + hybrid

    (calculs + client MQTT) MQTT (brokers) raiders (clients MQTT) basestar + hybrid (calculs + client MQTT) basestar + hybrid (calculs + client MQTT)
  15. #JSC2015 @k33g_org #GOLOBSG Le Plan Phase 2 coap & hazelcast

    j’ai choisi de faire “autrem ent”
  16. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1I basestar + hybrid

    (calculs + message) raiders (“serveurs”) basestar + hybrid (calculs + message) basestar + hybrid (calculs + message) partage des raiders >> pas de broker
  17. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1I basestar + hybrid

    (calculs + client COAP) raiders (“serveurs” COAP) basestar + hybrid (calculs + client COAP) basestar + hybrid (calculs + client COAP) CoAP
  18. #JSC2015 @k33g_org #GOLOBSG CoAP? “Protocole d’applications contraintes” Un protocole RESTful:

    Request/Response GET, POST, PUT, DELETE Pensé pour les réseaux LoWPAN (Low-Power Wireless Personal Area Network) = Réseaux de toutes petites machines Messages légers pour des devices très simples Le serveur est “sur” le hub ou l’objet connecté (tout dépend les possibilités de l’objet)
  19. #JSC2015 @k33g_org #GOLOBSG CoAP(Ressource)+Java class ObjectResource extends CoapResource {
 @Override


    public void handleGET(CoapExchange exchange) {
 exchange.respond("Hello World!");
 }
 @Override
 public void handlePOST(CoapExchange exchange) {
 exchange.accept();
 System.out.println(exchange.getRequestText());
 exchange.respond("{\"message\":\"Hello World!\"}");
 }
 public ObjectResource(String name) {
 super(name);
 }
 }

  20. #JSC2015 @k33g_org #GOLOBSG CoAP(Server)+Java 
 public class ObjectServer {
 public

    static void main(String [ ] args) {
 CoapServer server = new CoapServer();
 server.add(new ObjectResource("hello"));
 server.start();
 }
 }
  21. #JSC2015 @k33g_org #GOLOBSG CoAP(Client)+Java CoapClient client = new CoapClient("coap://127.0.0.1:5683/hello");
 


    System.out.println(client.get().getResponseText());
 // Hello World!
 CoapResponse response = client.post( "{\"message\":\"Salut!\"}", MediaTypeRegistry.APPLICATION_JSON );
 
 System.out.println(response.isSuccess());
 // true
 System.out.println(response.getResponseText());
 // {"message":"Hello World!"}
  22. #JSC2015 @k33g_org #GOLOBSG CoAP(Resource)+Golo function coapResource = |identifier, onGet, onPost|

    {
 
 let coapResourceDefinition = Adapter()
 : extends("org.eclipse.californium.core.CoapResource")
 : implements("handleGET", |this, coapExchange| {
 onGet(coapExchange)
 })
 : implements("handlePOST", |this, coapExchange| {
 onPost(coapExchange)
 })
 
 let coapResourceInstance = coapResourceDefinition: newInstance(identifier) 
 
 return coapResourceInstance 
 
 }
  23. #JSC2015 @k33g_org #GOLOBSG CoAP(Server)+Golo let resource = coapResource(
 identifier =

    "hello"
 , onGet = |exchange| {
 exchange: respond("Hello World!")
 }
 , onPost = |exchange| {
 exchange: accept()
 println(exchange: getRequestText())
 exchange: respond(
 JSON.stringify(
 map[["message", "Hello World!"]]
 )) 
 } 
 )
 
 let srv = CoapServer()
 srv: add(resource)
 srv: start()

  24. #JSC2015 @k33g_org #GOLOBSG CoAP(Client)+Golo let client = CoapClient("coap://127.0.0.1:5683/hello")
 
 let

    text = client: get(): getResponseText() # blocking call
 println(text)
 
 let response = client: post(
 JSON.stringify(map[["message", "hello"]]), 
 APPLICATION_JSON()
 )
 println( response: isSuccess() )
 println( response: getResponseText())
  25. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1I basestar + hybrid

    (calculs + client COAP) raiders (“serveurs” COAP)
  26. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1I basestar + hybrid

    (calculs + client COAP) raiders (“serveurs” COAP) ajout d’un basestar nouvelle répartition
  27. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1I basestar + hybrid

    (calculs + client COAP) raiders (“serveurs” COAP) encore un!
  28. #JSC2015 @k33g_org #GOLOBSG Le Plan: Phase 1I basestar + hybrid

    (calculs + client COAP) raiders (“serveurs” COAP) on en enlève un!
  29. #JSC2015 @k33g_org #GOLOBSG Hazelcast Grille de donnée mémoire (In Memory

    Data Grid)(Espace mémoire partagé) Stockage et le traitement de données réparties en cluster
  30. #JSC2015 @k33g_org #GOLOBSG Écrit en Java, Caches locaux et distribués,

    Clients natifs pour les langages Java, C#, … API Rest, Découverte automatique des membres, Failover automatique (un crash de nœud ne perd pas de données), Support des transactions et des locks, … Hazelcast quelques fonctionnalités
  31. #JSC2015 @k33g_org #GOLOBSG Hazelcast (java) HazelcastInstance hz = Hazelcast.newHazelcastInstance(cfg);
 //distributed

    map instance
 IMap<String, Integer> cylons = hz.getMap(“cylons");
 
 cylons.put("one", 0);
 cylons.put("two", 0);
 // …
 
 cylons.forEach((key, value) -> {
 System.out.println(key + " " + value);
 }); 
 cylons.localKeySet().forEach((k)->{
 cylons.put(k, cylons.get(k) + 1);
 });
  32. #JSC2015 @k33g_org #GOLOBSG en attente de coordonnées de départ 1.

    charger la liste d’adresses des raiders 2. parcourir la liste 1. pour chaque adresse: un client CoAP -> contact 2. attend que le raider lui réponde: WaitForRaider 1. si les coordonnées du raider son nulles (il n’a pas été contacté) 1. coordonnées de départ 2. affecte une couleur 3. mise à jour de la map Hazelcast (mais pas envoi) 3. Puis …
  33. #JSC2015 @k33g_org #GOLOBSG 1. Puis, j’attends : WhenAllRaiders (all raiders

    OK?) 1. parcours de la map locale 2. envoyer coordonnées de départ (CoAP) 3. Puis attendre que les raiders accusent réception … while hybrid: raiders(): size(): equals(maxRaiders) is false {} this: raiders(): localKeySet(): each(|raiderKey| { … }) en attente de coordonnées de départ
  34. #JSC2015 @k33g_org #GOLOBSG 1. Une fois que tous les raiders

    sont initialisés: 1. WhenAllRaidersAreIgnited 1. Calculer les mouvements en fonction des contraintes et des autres raiders 2. Envoyer via CoAP les nouvelles coordonnées aux raiders (de la map locale) 1. déplacement du raider 2. envoyer coordonnées à l’interface de “monitoring” Raiders “in action”
  35. #JSC2015 @k33g_org #GOLOBSG Dynamic code evaluation let execEnv = gololang.EvaluationEnvironment()


    
 let sourceCode = """
 function hello = |name| {
 println("hello " + name)
 return 42
 }
 function salut = |name| {
 println("salut " + name)
 }
 """
 let myModule = execEnv: anonymousModule(sourceCode) # compile
 
 let res = fun("hello", myModule)("Bob") # res=42
 fun("salut", myModule)("Sam")
  36. #JSC2015 @k33g_org #GOLOBSG Modification des raiders let raiderResource = coapResource("raider"

    + this: id(): toString(),
 |exchange| { # onPost
 exchange: accept()
 let data = JSON.parse(exchange: getRequestText()) # data from hybrid
 if cmd: equals("move") {…} 
 if cmd: equals("exec") { # run method
 let plugin = getExecutionEnvironment() : anonymousModule(data: get("src")) # compile
 fun(data: get("name"), plugin)(this) 
 } 
 exchange: respond(CREATED())
 }
 )