The Plan v3 pour BDX.io

The Plan v3 pour BDX.io

03c0a459fd631e867bade2cc95517a4f?s=128

Philippe CHARRIERE

November 10, 2017
Tweet

Transcript

  1. #BSGTHEPLAN #BDXIO17 The Plan

  2. #BSGTHEPLAN #BDXIO17 bonjour Philippe CharriĂšre @clever_cloud ! @k33g_org G @k33g

    I ❀JavaScript, I Java, I JVM, I Scala (depuis peu
)
  3. #BSGTHEPLAN #BDXIO17 Les origines de ce talk? DĂ©mos clients Monter

    en compĂ©tence sur les microservices (et vert.x) partager ce que j’ai appris (~ tuto) https://github.com/the-plan
  4. #BSGTHEPLAN #BDXIO17 Microservices ???

  5. #BSGTHEPLAN #BDXIO17 –Philippe Charriùre “Les microservices sont des morceaux d’application(s)

    dĂ©veloppĂ©s de maniĂšre indĂ©pendante, dĂ©ployĂ©s de maniĂšre indĂ©pendante et gĂ©rĂ©s par de petites Ă©quipes ” “Un microservice est petit, car il rĂ©sout un seul problĂšme”
  6. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ?

  7. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ? Avoir un seul

    objectif Encapsulation Appropriation par l’équipe Autonomie de l’équipe Versions multiples ChorĂ©graphie Eventual consistency (cohĂ©rence Ă  terme)
  8. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ? Avoir un seul

    objectif Encapsulation Appropriation par l’équipe Autonomie de l’équipe Versions multiples ChorĂ©graphie Eventual consistency (cohĂ©rence Ă  terme)
  9. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ? Avoir un seul

    objectif Encapsulation Appropriation par l’équipe Autonomie de l’équipe Versions multiples ChorĂ©graphie Eventual consistency (cohĂ©rence Ă  terme)
  10. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ? Avoir un seul

    objectif Encapsulation Appropriation par l’équipe Autonomie de l’équipe Versions multiples ChorĂ©graphie Eventual consistency (cohĂ©rence Ă  terme)
  11. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ? Avoir un seul

    objectif Encapsulation Appropriation par l’équipe Autonomie de l’équipe Versions multiples ChorĂ©graphie Eventual consistency (cohĂ©rence Ă  terme)
  12. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ? Avoir un seul

    objectif Encapsulation Appropriation par l’équipe Autonomie de l’équipe Versions multiples ChorĂ©graphie Eventual consistency (cohĂ©rence Ă  terme)
  13. #BSGTHEPLAN #BDXIO17 Les qualitĂ©s d’un microservice ? Avoir un seul

    objectif Encapsulation Appropriation par l’équipe Autonomie de l’équipe Versions multiples ChorĂ©graphie Eventual consistency (cohĂ©rence Ă  terme)
  14. #BSGTHEPLAN #BDXIO17 Pourquoi c’est bien ? 
 les microservices

  15. #BSGTHEPLAN #BDXIO17 Pourquoi c’est bien ? Time to Market plus

    rapide Code moins compliquĂ© et meilleur ResponsabilitĂ© Des niveaux d’expertise Ă©levĂ©s par Ă©quipe Externalisation plus facile SecuritĂ©
  16. #BSGTHEPLAN #BDXIO17 Pourquoi c’est bien ? Time to Market plus

    rapide Code moins compliquĂ© et meilleur ResponsabilitĂ© Des niveaux d’expertise Ă©levĂ©s par Ă©quipe Externalisation plus facile SecuritĂ©
  17. #BSGTHEPLAN #BDXIO17 Pourquoi c’est bien ? Time to Market plus

    rapide Code moins compliquĂ© et meilleur ResponsabilitĂ© Des niveaux d’expertise Ă©levĂ©s par Ă©quipe Externalisation plus facile SecuritĂ©
  18. #BSGTHEPLAN #BDXIO17 Pourquoi c’est bien ? Time to Market plus

    rapide Code moins compliquĂ© et meilleur ResponsabilitĂ© Des niveaux d’expertises Ă©levĂ©s par Ă©quipe Externalisation plus facile SecuritĂ©
  19. #BSGTHEPLAN #BDXIO17 Pourquoi c’est bien ? Time to Market plus

    rapide Code moins compliquĂ© et meilleur ResponsabilitĂ© Des niveaux d’expertises Ă©levĂ©s par Ă©quipe Externalisation plus facile SecuritĂ©
  20. #BSGTHEPLAN #BDXIO17 Pourquoi c’est bien ? Time to Market plus

    rapide Code moins compliquĂ© et meilleur ResponsabilitĂ© Des niveaux d’expertises Ă©levĂ©s par Ă©quipe Externalisation plus facile SĂ©curitĂ©
  21. #BSGTHEPLAN #BDXIO17 Pourquoi ce n’est pas toujours simple ? 


    les microservices
  22. #BSGTHEPLAN #BDXIO17 Pourquoi ce n’est pas toujours simple ? ComplexitĂ©

    externe MaturitĂ© “organisationnelle” Duplication (multiplication) Eventual consistency (cohĂ©rence Ă  terme) Testing, simple 
 ou pas Monitoring
  23. #BSGTHEPLAN #BDXIO17 Pourquoi ce n’est pas toujours simple ? ComplexitĂ©

    externe MaturitĂ© “organisationnelle” Duplication (multiplication) Eventual consistency (cohĂ©rence Ă  terme) Testing, simple 
 ou pas Monitoring
  24. #BSGTHEPLAN #BDXIO17 Pourquoi ce n’est pas toujours simple ? ComplexitĂ©

    externe MaturitĂ© “organisationnelle” Duplication (multiplication) Eventual consistency (cohĂ©rence Ă  terme) Testing, simple 
 ou pas Monitoring
  25. #BSGTHEPLAN #BDXIO17 Pourquoi ce n’est pas toujours simple ? ComplexitĂ©

    externe MaturitĂ© “organisationnelle” Duplication (multiplication) Eventual consistency (cohĂ©rence Ă  terme) Testing, simple 
 ou pas Monitoring
  26. #BSGTHEPLAN #BDXIO17 Pourquoi ce n’est pas toujours simple ? ComplexitĂ©

    externe MaturitĂ© “organisationnelle” Duplication (multiplication) Eventual consistency (cohĂ©rence Ă  terme) Testing, simple 
 ou pas Monitoring
  27. #BSGTHEPLAN #BDXIO17 Pourquoi ce n’est pas toujours simple ? ComplexitĂ©

    externe MaturitĂ© “organisationnelle” Duplication (multiplication) Eventual consistency (cohĂ©rence Ă  terme) Testing, simple 
 ou pas Monitoring
  28. #BSGTHEPLAN #BDXIO17 VERT.X Projet RedHat #BSGTHEPLAN #BDXIO17

  29. #BSGTHEPLAN #BDXIO17 Pourquoi Vert.x Pas besoin de serveur d’application, de

    servlet Simple (à utiliser, à coder, à builder, à déployer) Polyglotte Comme à la maison, on dirait du #JavaScript Asynchrone Une dream team
  30. #BSGTHEPLAN #BDXIO17 microservices Vert.x En ce qui concerne la partie

    Microservices Agnostique sur la partie Discovery Léger Des composants pour une architecture stable & résilience: Health Checks Circuit Breakers 

  31. #BSGTHEPLAN #BDXIO17 microservices Vert.x

  32. #BSGTHEPLAN #BDXIO17 Une intro Ă  Vert.x http://vertx.io/docs/guide-for-java-devs/

  33. #BSGTHEPLAN #BDXIO17 #BSGTHEPLAN #BDXIO17

  34. #BSGTHEPLAN #BDXIO17 1 microservice REST Vert.x public class BaseStar extends

    AbstractVerticle { public void start() { Router router = Router.router(vertx); router.route().handler(BodyHandler.create()); router.get("/api/hello").handler(context -> { context.response() .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("message", "hello").encodePrettily()); }); Integer httpPort = 8080; HttpServer server = vertx.createHttpServer(); server.requestHandler(router::accept).listen(httpPort, result -> { System.out.println(" Listening on " + httpPort); }); } }
  35. #BSGTHEPLAN #BDXIO17 micro, m’ouais 
 Distribuer les fonctionnalitĂ©s et les

    donnĂ©es IdentiïŹer les microservices, les trouver, 
 GĂ©rer la cohĂ©rence et la ïŹabilitĂ© du rĂ©seau pour chacun Composants distribuĂ©s + Technologies diïŹ€Ă©rentes = “new modes of failure” Quand ça ne marche pas 
 ComplexitĂ© d’investigation
  36. #BSGTHEPLAN #BDXIO17 Le Plan Redis + http

  37. #BSGTHEPLAN #BDXIO17 objectifs #BSGTHEPLAN #BDXIO17

  38. #BSGTHEPLAN #BDXIO17 Plan de “the plan” BaseStars WebApp Raiders Conclusion(s)

  39. #BSGTHEPLAN #BDXIO17 BaseStar Java

  40. #BSGTHEPLAN #BDXIO17 BaseStar Service Discovery & Backend

  41. #BSGTHEPLAN #BDXIO17 s’enregistrer BaseStar JAVA BaseStar JAVA BaseStar JAVA BaseStar

    JAVA REDIS BaseStar JAVA
  42. #BSGTHEPLAN #BDXIO17 s’enregistrer - ServiceDiscovery public class BaseStar extends AbstractVerticle

    { public void start() { // Discovery settings ServiceDiscoveryOptions serviceDiscoveryOptions = new ServiceDiscoveryOptions(); // Redis settings with the standard Redis Backend Integer redisPort = Integer.parseInt(Optional.ofNullable(System.getenv("REDIS_PORT")).orElse("6379")); String redisHost = Optional.ofNullable(System.getenv("REDIS_HOST")).orElse("127.0.0.1"); String redisAuth = Optional.ofNullable(System.getenv("REDIS_PASSWORD")).orElse(null); String redisRecordsKey = Optional.ofNullable(System.getenv("REDIS_RECORDS_KEY")).orElse("vert.x.ms"); discovery = ServiceDiscovery.create( vertx, serviceDiscoveryOptions.setBackendConfiguration( new JsonObject() .put("host", redisHost) .put("port", redisPort) .put("auth", redisAuth) .put("key", redisRecordsKey) )); } }
  43. #BSGTHEPLAN #BDXIO17 s’enregistrer - ServiceDiscovery public class BaseStar extends AbstractVerticle

    { public void start() { // Discovery settings ServiceDiscoveryOptions serviceDiscoveryOptions = new ServiceDiscoveryOptions(); // Redis settings with the standard Redis Backend Integer redisPort = Integer.parseInt(Optional.ofNullable(System.getenv("REDIS_PORT")).orElse("6379")); String redisHost = Optional.ofNullable(System.getenv("REDIS_HOST")).orElse("127.0.0.1"); String redisAuth = Optional.ofNullable(System.getenv("REDIS_PASSWORD")).orElse(null); String redisRecordsKey = Optional.ofNullable(System.getenv("REDIS_RECORDS_KEY")).orElse("vert.x.ms"); discovery = ServiceDiscovery.create( vertx, serviceDiscoveryOptions.setBackendConfiguration( new JsonObject() .put("host", redisHost) .put("port", redisPort) .put("auth", redisAuth) .put("key", redisRecordsKey) )); } }
  44. #BSGTHEPLAN #BDXIO17 s’enregistrer - Record public class BaseStar extends AbstractVerticle

    { public void start() { // microservice options Haikunator haikunator = new HaikunatorBuilder().setTokenLength(6).build(); String niceName = haikunator.haikunate(); String serviceName = Optional.ofNullable(System.getenv("SERVICE_NAME")).orElse("the-plan")+"-"+niceName; String serviceHost = Optional.ofNullable(System.getenv("SERVICE_HOST")).orElse("localhost"); Integer servicePort = Integer.parseInt(Optional.ofNullable(System.getenv("SERVICE_PORT")).orElse("80")); String serviceRoot = Optional.ofNullable(System.getenv("SERVICE_ROOT")).orElse("/api"); String color = Optional.ofNullable(System.getenv("COLOR")).orElse("FFD433"); // create the microservice record record = HttpEndpoint.createRecord( serviceName, serviceHost, servicePort, serviceRoot ); } }
  45. #BSGTHEPLAN #BDXIO17 s’enregistrer - MetaData public class BaseStar extends AbstractVerticle

    { public void start() { // add some metadata record.setMetadata(new JsonObject() .put("kind", "basestar") .put("message", "Hello ") .put("uri", "/coordinates") .put("raiders_counter", raidersCounter) .put("color", color) .put("app_id", Optional.ofNullable(System.getenv("APP_ID")).orElse("")) .put("instance_id", Optional.ofNullable(System.getenv("INSTANCE_ID")).orElse("")) .put("instance_type", Optional.ofNullable(System.getenv("INSTANCE_TYPE")).orElse("production")) .put("instance_number", Integer.parseInt(Optional.ofNullable(System.getenv("INSTANCE_NUMBER")).orElse("0"))) ); } }
  46. #BSGTHEPLAN #BDXIO17 s’enregistrer & dĂ©marrer public class BaseStar extends AbstractVerticle

    { public void start() { Integer httpPort = Integer.parseInt(Optional.ofNullable(System.getenv("PORT")).orElse("8080")); HttpServer server = vertx.createHttpServer(); server.requestHandler(router::accept).listen(httpPort, result -> { if(result.succeeded()) { System.out.println(" Listening on " + httpPort); //publish the microservice to the discovery backend discovery.publish(record, asyncResult -> { if(asyncResult.succeeded()) { System.out.println("" + record.getRegistration()); } else { System.out.println("" + asyncResult.cause().getMessage()); } }); } else { System.out.println(" Houston, we have a problem: " + result.cause().getMessage()); } }); } }
  47. #BSGTHEPLAN #BDXIO17 s’enregistrer & dĂ©marrer public class BaseStar extends AbstractVerticle

    { public void start() { Integer httpPort = Integer.parseInt(Optional.ofNullable(System.getenv("PORT")).orElse("8080")); HttpServer server = vertx.createHttpServer(); server.requestHandler(router::accept).listen(httpPort, result -> { if(result.succeeded()) { System.out.println(" Listening on " + httpPort); //publish the microservice to the discovery backend discovery.publish(record, asyncResult -> { if(asyncResult.succeeded()) { System.out.println("" + record.getRegistration()); } else { System.out.println("" + asyncResult.cause().getMessage()); } }); } else { System.out.println(" Houston, we have a problem: " + result.cause().getMessage()); } }); } }
  48. #BSGTHEPLAN #BDXIO17 BaseStar Routes | Router

  49. #BSGTHEPLAN #BDXIO17 Routes | Router public class BaseStar extends AbstractVerticle

    { public void start() { Router router = Router.router(vertx); router.route().handler(BodyHandler.create()); router.get("/api/raiders").handler(context -> { discovery.getRecords(r -> r.getMetadata().getString("kind").equals("raider") , ar -> { if (ar.succeeded()) { context.response() .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonArray(ar.result()).encodePrettily()); } }); }); // serve static assets, see /resources/webroot directory router.route("/*").handler(StaticHandler.create()); Integer httpPort = Integer.parseInt(Optional.ofNullable(System.getenv("PORT")).orElse("8080")); HttpServer server = vertx.createHttpServer(); server.requestHandler(router::accept).listen(httpPort, result -> { }); } }
  50. #BSGTHEPLAN #BDXIO17 GET | /api/raiders public class BaseStar extends AbstractVerticle

    { public void start() { Router router = Router.router(vertx); router.route().handler(BodyHandler.create()); router.get("/api/raiders").handler(context -> { discovery.getRecords(r -> r.getMetadata().getString("kind").equals("raider") , ar -> { if (ar.succeeded()) { context.response() .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonArray(ar.result()).encodePrettily()); } }); }); // serve static assets, see /resources/webroot directory router.route("/*").handler(StaticHandler.create()); Integer httpPort = Integer.parseInt(Optional.ofNullable(System.getenv("PORT")).orElse("8080")); HttpServer server = vertx.createHttpServer(); server.requestHandler(router::accept).listen(httpPort, result -> { }); } }
  51. #BSGTHEPLAN #BDXIO17 Permettre aux raiders de “s’enregistrer”

  52. #BSGTHEPLAN #BDXIO17 POST | /api/raiders public class BaseStar extends AbstractVerticle

    { public void start() { router.post("/api/raiders").handler(context -> { // I'm a new raider String registationId = Optional.ofNullable(context.getBodyAsJson().getString("registration")).orElse("unknown"); discovery.getRecord(r -> r.getRegistration().equals(registationId), asyncResRecord -> { // = raider's record if(asyncResRecord.succeeded()) { Record raiderRecord = asyncResRecord.result(); ServiceReference reference = discovery.getReference(raiderRecord); WebClient raiderClient = reference.getAs(WebClient.class); // ⚠ get a web client this.raidersCounter += 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, ar -> { }); this.raiderWorker(raiderRecord,raiderClient); // this is a worker context.response() // ✉ message to the raider .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("message", "ok, registered").encodePrettily()); } }); }); } }
  53. #BSGTHEPLAN #BDXIO17 POST | /api/raiders public class BaseStar extends AbstractVerticle

    { public void start() { router.post("/api/raiders").handler(context -> { // I'm a new raider String registationId = Optional.ofNullable(context.getBodyAsJson().getString("registration")).orElse("unknown"); discovery.getRecord(r -> r.getRegistration().equals(registationId), asyncResRecord -> { // = raider's record if(asyncResRecord.succeeded()) { Record raiderRecord = asyncResRecord.result(); ServiceReference reference = discovery.getReference(raiderRecord); WebClient raiderClient = reference.getAs(WebClient.class); // ⚠ get a web client this.raidersCounter += 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, ar -> { }); this.raiderWorker(raiderRecord,raiderClient); // this is a worker context.response() // ✉ message to the raider .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("message", "ok, registered").encodePrettily()); } }); }); } }
  54. #BSGTHEPLAN #BDXIO17 POST | /api/raiders public class BaseStar extends AbstractVerticle

    { public void start() { router.post("/api/raiders").handler(context -> { // I'm a new raider String registationId = Optional.ofNullable(context.getBodyAsJson().getString("registration")).orElse("unknown"); discovery.getRecord(r -> r.getRegistration().equals(registationId), asyncResRecord -> { // = raider's record if(asyncResRecord.succeeded()) { Record raiderRecord = asyncResRecord.result(); ServiceReference reference = discovery.getReference(raiderRecord); WebClient raiderClient = reference.getAs(WebClient.class); // ⚠ get a web client this.raidersCounter += 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, ar -> { }); this.raiderWorker(raiderRecord,raiderClient); // this is a worker context.response() // ✉ message to the raider .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("message", "ok, registered").encodePrettily()); } }); }); } }
  55. #BSGTHEPLAN #BDXIO17 POST | /api/raiders public class BaseStar extends AbstractVerticle

    { public void start() { router.post("/api/raiders").handler(context -> { // I'm a new raider String registationId = Optional.ofNullable(context.getBodyAsJson().getString("registration")).orElse("unknown"); discovery.getRecord(r -> r.getRegistration().equals(registationId), asyncResRecord -> { // = raider's record if(asyncResRecord.succeeded()) { Record raiderRecord = asyncResRecord.result(); ServiceReference reference = discovery.getReference(raiderRecord); WebClient raiderClient = reference.getAs(WebClient.class); // ⚠ get a web client this.raidersCounter += 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, ar -> { }); this.raiderWorker(raiderRecord,raiderClient); // this is a worker context.response() // ✉ message to the raider .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("message", "ok, registered").encodePrettily()); } }); }); } }
  56. #BSGTHEPLAN #BDXIO17 POST | /api/raiders public class BaseStar extends AbstractVerticle

    { public void start() { router.post("/api/raiders").handler(context -> { // I'm a new raider String registationId = Optional.ofNullable(context.getBodyAsJson().getString("registration")).orElse("unknown"); discovery.getRecord(r -> r.getRegistration().equals(registationId), asyncResRecord -> { // = raider's record if(asyncResRecord.succeeded()) { Record raiderRecord = asyncResRecord.result(); ServiceReference reference = discovery.getReference(raiderRecord); WebClient raiderClient = reference.getAs(WebClient.class); // ⚠ get a web client this.raidersCounter += 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, ar -> { }); this.raiderWorker(raiderRecord,raiderClient); // this is a worker context.response() // ✉ message to the raider .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("message", "ok, registered").encodePrettily()); } }); }); } }
  57. #BSGTHEPLAN #BDXIO17 BaseStar HealthCheck ❀ Hey, toujours lĂ  ?

  58. #BSGTHEPLAN #BDXIO17 HealthCheck ❀ public class BaseStar extends AbstractVerticle {

    public void start() { // health check of existing basestars HealthCheckHandler hch = HealthCheckHandler.create(vertx); hch.register("iamok", future -> discovery.getRecord(r -> r.getRegistration().equals(record.getRegistration()), ar -> { if(ar.succeeded()) { future.complete(); } else { // future.fail(ar.cause()); } }) ); router.get("/health").handler(hch); } }
  59. #BSGTHEPLAN #BDXIO17 HealthCheck ❀ public class BaseStar extends AbstractVerticle {

    public void start() { // health check of existing basestars HealthCheckHandler hch = HealthCheckHandler.create(vertx); hch.register("iamok", future -> discovery.getRecord(r -> r.getRegistration().equals(record.getRegistration()), ar -> { if(ar.succeeded()) { future.complete(); } else { // future.fail(ar.cause()); } }) ); router.get("/health").handler(hch); } }
  60. #BSGTHEPLAN #BDXIO17 HealthCheck ❀ public class BaseStar extends AbstractVerticle {

    public void start() { // health check of existing basestars HealthCheckHandler hch = HealthCheckHandler.create(vertx); hch.register("iamok", future -> discovery.getRecord(r -> r.getRegistration().equals(record.getRegistration()), ar -> { if(ar.succeeded()) { future.complete(); } else { // future.fail(ar.cause()); } }) ); router.get("/health").handler(hch); } }
  61. #BSGTHEPLAN #BDXIO17 BaseStar Worker this.raiderWorker(raiderRecord,raiderClient); // this is a worker

    router.post("/api/raiders").handler(context -> { // I'm a new raider
  62. #BSGTHEPLAN #BDXIO17 Worker private void raiderWorker(Record raiderRecord, WebClient raiderClient) {

    Raider thatRaider = new Raider( raiderRecord.getRegistration(), raiderRecord.getName(), raiderRecord.getMetadata().getJsonObject("coordinates").getDouble("x"), raiderRecord.getMetadata().getJsonObject("coordinates").getDouble("y"), new Constraints(5.0, 600.0, 600.0, 5.0) ); //
 }
  63. #BSGTHEPLAN #BDXIO17 Worker private void raiderWorker(Record raiderRecord, WebClient raiderClient) {

    //
 vertx.setPeriodic(1000, timerID -> { // this is a worker // get the raiders list discovery.getRecords(r -> r.getMetadata().getString("kind").equals("raider") , ar -> { if(ar.succeeded()) { List<Record> raidersRecords = ar.result(); thatRaider.moveWith(raidersRecords, 300.0); thatRaider.moveCloser(raidersRecords, 300.0); thatRaider.moveAway(raidersRecords, 15.0); thatRaider.move(); // === try to contact the raider and post coordinates === raiderClient.post("/api/coordinates").sendJsonObject( new JsonObject() .put("x",thatRaider.x) .put("y",thatRaider.y) .put("xVelocity",thatRaider.xVelocity) .put("yVelocity",thatRaider.yVelocity), asyncPostRes -> { if(asyncPostRes.succeeded()) { System.out.println(" " + asyncPostRes.result().bodyAsJsonObject().encodePrettily()); } else { // ouch raidersCounter -= 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, asyncRecUpdateRes -> { vertx.cancelTimer(timerID);}); } } ); }); }); }
  64. #BSGTHEPLAN #BDXIO17 Worker private void raiderWorker(Record raiderRecord, WebClient raiderClient) {

    //
 vertx.setPeriodic(1000, timerID -> { // this is a worker // get the raiders list discovery.getRecords(r -> r.getMetadata().getString("kind").equals("raider") , ar -> { if(ar.succeeded()) { List<Record> raidersRecords = ar.result(); thatRaider.moveWith(raidersRecords, 300.0); thatRaider.moveCloser(raidersRecords, 300.0); thatRaider.moveAway(raidersRecords, 15.0); thatRaider.move(); // === try to contact the raider and post coordinates === raiderClient.post("/api/coordinates").sendJsonObject( new JsonObject() .put("x",thatRaider.x) .put("y",thatRaider.y) .put("xVelocity",thatRaider.xVelocity) .put("yVelocity",thatRaider.yVelocity), asyncPostRes -> { if(asyncPostRes.succeeded()) { System.out.println(" " + asyncPostRes.result().bodyAsJsonObject().encodePrettily()); } else { // ouch raidersCounter -= 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, asyncRecUpdateRes -> { vertx.cancelTimer(timerID);}); } } ); }); }); }
  65. #BSGTHEPLAN #BDXIO17 Worker private void raiderWorker(Record raiderRecord, WebClient raiderClient) {

    //
 vertx.setPeriodic(1000, timerID -> { // this is a worker // get the raiders list discovery.getRecords(r -> r.getMetadata().getString("kind").equals("raider") , ar -> { if(ar.succeeded()) { List<Record> raidersRecords = ar.result(); thatRaider.moveWith(raidersRecords, 300.0); thatRaider.moveCloser(raidersRecords, 300.0); thatRaider.moveAway(raidersRecords, 15.0); thatRaider.move(); // === try to contact the raider and post coordinates === raiderClient.post("/api/coordinates").sendJsonObject( new JsonObject() .put("x",thatRaider.x) .put("y",thatRaider.y) .put("xVelocity",thatRaider.xVelocity) .put("yVelocity",thatRaider.yVelocity), asyncPostRes -> { if(asyncPostRes.succeeded()) { System.out.println(" " + asyncPostRes.result().bodyAsJsonObject().encodePrettily()); } else { // ouch raidersCounter -= 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, asyncRecUpdateRes -> { vertx.cancelTimer(timerID);}); } } ); }); }); }
  66. #BSGTHEPLAN #BDXIO17 Worker private void raiderWorker(Record raiderRecord, WebClient raiderClient) {

    //
 vertx.setPeriodic(1000, timerID -> { // this is a worker // get the raiders list discovery.getRecords(r -> r.getMetadata().getString("kind").equals("raider") , ar -> { if(ar.succeeded()) { List<Record> raidersRecords = ar.result(); thatRaider.moveWith(raidersRecords, 300.0); thatRaider.moveCloser(raidersRecords, 300.0); thatRaider.moveAway(raidersRecords, 15.0); thatRaider.move(); // === try to contact the raider and post coordinates === raiderClient.post("/api/coordinates").sendJsonObject( new JsonObject() .put("x",thatRaider.x) .put("y",thatRaider.y) .put("xVelocity",thatRaider.xVelocity) .put("yVelocity",thatRaider.yVelocity), asyncPostRes -> { if(asyncPostRes.succeeded()) { System.out.println(" " + asyncPostRes.result().bodyAsJsonObject().encodePrettily()); } else { // ouch raidersCounter -= 1; record.getMetadata().put("raiders_counter", raidersCounter); discovery.update(record, asyncRecUpdateRes -> { vertx.cancelTimer(timerID);}); } } ); }); }); }
  67. #BSGTHEPLAN #BDXIO17 RĂ©capitulatif BaseStar JAVA BaseStar JAVA BaseStar JAVA BaseStar

    JAVA REDIS BaseStar JAVA GET http://localhost:808N/api/raiders POST http://localhost:808N/api/raiders GET http://localhost:808N/health Raider KOTLIN Raider KOTLIN Raider GROOVY Raider GROOVY POST http://localhost:909N/api/coordinates Hey pilotage
  68. #BSGTHEPLAN #BDXIO17 checklist ✅ DĂ©marrer les BaseStars ✅ cf Base

    Redis - MEDIS & health ✅ DĂ©marrer Redis
  69. #BSGTHEPLAN #BDXIO17 WebApp Scala + JavaScript

  70. #BSGTHEPLAN #BDXIO17 WebApp BaseStar JAVA BaseStar JAVA BaseStar JAVA REDIS

    BaseStar JAVA GET http://localhost:808N/api/raiders POST http://localhost:808N/api/raiders GET http://localhost:808N/health BSG monitor SCALA GET http://localhost:8080/api/raiders BSG map JS http://localhost:7070 BaseStar JAVA Raider KOTLIN Raider KOTLIN Raider GROOVY Raider GROOVY POST http://localhost:909N/api/coordinates
  71. #BSGTHEPLAN #BDXIO17 WebApp | Backend Scala val httpPort = sys.env.getOrElse("PORT",

    "8080").toInt router.get("/api/raiders").handler(context => { discovery .getRecordsFuture(record => record.getMetadata.getString("kind").equals("raider")) .onComplete { case Success(results) => { context .response() .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonArray(results.toList.asJava).encodePrettily()) } case Failure(cause) => { context .response() .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("error", cause.getMessage).encodePrettily()) } } }) router.route("/*").handler(StaticHandler.create()) println(s" Listening on $httpPort - Enjoy ") server.requestHandler(router.accept _).listen(httpPort)
  72. #BSGTHEPLAN #BDXIO17 WebApp | Backend Scala val httpPort = sys.env.getOrElse("PORT",

    "8080").toInt router.get("/api/raiders").handler(context => { discovery .getRecordsFuture(record => record.getMetadata.getString("kind").equals("raider")) .onComplete { case Success(results) => { context .response() .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonArray(results.toList.asJava).encodePrettily()) } case Failure(cause) => { context .response() .putHeader("content-type", "application/json;charset=UTF-8") .end(new JsonObject().put("error", cause.getMessage).encodePrettily()) } } }) router.route("/*").handler(StaticHandler.create()) println(s" Listening on $httpPort - Enjoy ") server.requestHandler(router.accept _).listen(httpPort)
  73. #BSGTHEPLAN #BDXIO17 checklist ✅ DĂ©marrer les BaseStars ✅ cf Base

    Redis - MEDIS ✅ DĂ©marrer Redis ✅ DĂ©marrer BSG Monitor ✅ DĂ©marrer BSG Map
  74. #BSGTHEPLAN #BDXIO17 Raider(s)

  75. #BSGTHEPLAN #BDXIO17 Raider(s) BaseStar JAVA BaseStar JAVA BaseStar JAVA REDIS

    BaseStar JAVA GET http://localhost:808N/api/raiders POST http://localhost:808N/api/raiders GET http://localhost:808N/health BSG monitor SCALA GET http://localhost:8080/api/raiders BSG map JS http://localhost:7070 BaseStar JAVA Raider KOTLIN Raider KOTLIN Raider GROOVY Raider GROOVY POST http://localhost:909N/api/coordinates Raider GROOVY Raider KOTLIN Raider GROOVY
  76. #BSGTHEPLAN #BDXIO17 Raider(s) | main + stop kotlin

  77. #BSGTHEPLAN #BDXIO17 Raider(s) | main + stop fun main(args: Array<String>)

    { val vertx = Vertx.vertx() vertx.deployVerticle(Raider()) } class Raider : AbstractVerticle() { override fun stop(stopFuture: Future<Void>) { super.stop() println("Unregistration process is started (${record?.registration})...") discovery?.unpublish(record?.registration, { ar -> when { ar.failed() -> { println(" Unable to unpublish the microservice: ${ar.cause().message}") stopFuture.fail(ar.cause()) } ar.succeeded() -> { println(" bye bye ${record?.registration}") stopFuture.complete() } } }) } override fun start() { 
 } }
  78. #BSGTHEPLAN #BDXIO17 Raider(s) | main + stop fun main(args: Array<String>)

    { val vertx = Vertx.vertx() vertx.deployVerticle(Raider()) } class Raider : AbstractVerticle() { override fun stop(stopFuture: Future<Void>) { super.stop() println("Unregistration process is started (${record?.registration})...") discovery?.unpublish(record?.registration, { ar -> when { ar.failed() -> { println(" Unable to unpublish the microservice: ${ar.cause().message}") stopFuture.fail(ar.cause()) } ar.succeeded() -> { println(" bye bye ${record?.registration}") stopFuture.complete() } } }) } override fun start() { 
 } }
  79. #BSGTHEPLAN #BDXIO17 Raider(s) | start / discovery kotlin

  80. #BSGTHEPLAN #BDXIO17 Raider(s) | s’enregistrer / ServiceDiscovery class Raider :

    AbstractVerticle() { override fun start() { /* === Discovery part === */ val redisPort= System.getenv("REDIS_PORT")?.toInt() ?: 6379 val redisHost = System.getenv("REDIS_HOST") ?: "127.0.0.1" val redisAuth = System.getenv("REDIS_PASSWORD") ?: null val redisRecordsKey = System.getenv("REDIS_RECORDS_KEY") ?: "vert.x.ms" val serviceDiscoveryOptions = ServiceDiscoveryOptions() discovery = ServiceDiscovery.create(vertx, serviceDiscoveryOptions.setBackendConfiguration( json { obj( "host" to redisHost, "port" to redisPort, "auth" to redisAuth, "key" to redisRecordsKey ) } )) } }
  81. #BSGTHEPLAN #BDXIO17 Raider(s) | s’enregistrer / Record class Raider :

    AbstractVerticle() { override fun start() { // microservice informations val haikunator = HaikunatorBuilder().setTokenLength(3).build() val niceName = haikunator.haikunate() val serviceName = "${System.getenv("SERVICE_NAME") ?: "the-plan"}-$niceName" val serviceHost = System.getenv("SERVICE_HOST") ?: "localhost" val servicePort = System.getenv("SERVICE_PORT")?.toInt() ?: 80 val serviceRoot = System.getenv("SERVICE_ROOT") ?: "/api" // create the microservice record record = HttpEndpoint.createRecord( serviceName, serviceHost, servicePort, serviceRoot ) } }
  82. #BSGTHEPLAN #BDXIO17 Raider(s) | s’enregistrer / metadata class Raider :

    AbstractVerticle() { override fun start() { // add metadata record?.metadata = json { obj( "kind" to "raider", "message" to " ready to fight", "basestar" to null, "coordinates" to obj( "x" to random(0.0, 400.0), "y" to random(0.0, 400.0) ), "app_id" to (System.getenv("APP_ID") ?: ""), "instance_id" to (System.getenv("INSTANCE_ID") ?: ""), "instance_type" to (System.getenv("INSTANCE_TYPE") ?: "production"), "instance_number" to (Integer.parseInt(System.getenv("INSTANCE_NUMBER") ?: "0")) ) } } }
  83. #BSGTHEPLAN #BDXIO17 Raider(s) | s’enregistrer / dĂ©marrer class Raider :

    AbstractVerticle() { override fun start() { val httpPort = System.getenv("PORT")?.toInt() ?: 8080 vertx.createHttpServer(HttpServerOptions(port = httpPort)) .requestHandler { router.accept(it) } .listen { ar -> when { ar.failed() -> println(" Houston?") ar.succeeded() -> { println(" Raider started on $httpPort") /* === publish the microservice record to the discovery backend === */ discovery?.publish(record, { asyncRes -> when { asyncRes.failed() -> println(" ${asyncRes.cause().message}") asyncRes.succeeded() -> { println(" ${asyncRes.result().registration}") /* === search for a baseStar === */ searchAndSelectOneBaseStar() } } }) /* === end of publish === } } } } }
  84. #BSGTHEPLAN #BDXIO17 Raider(s) | s’enregistrer / dĂ©marrer class Raider :

    AbstractVerticle() { override fun start() { val httpPort = System.getenv("PORT")?.toInt() ?: 8080 vertx.createHttpServer(HttpServerOptions(port = httpPort)) .requestHandler { router.accept(it) } .listen { ar -> when { ar.failed() -> println(" Houston?") ar.succeeded() -> { println(" Raider started on $httpPort") /* === publish the microservice record to the discovery backend === */ discovery?.publish(record, { asyncRes -> when { asyncRes.failed() -> println(" ${asyncRes.cause().message}") asyncRes.succeeded() -> { println(" ${asyncRes.result().registration}") /* === search for a baseStar === */ searchAndSelectOneBaseStar() } } }) /* === end of publish === } } } } }
  85. #BSGTHEPLAN #BDXIO17 Raider Routes | Router

  86. #BSGTHEPLAN #BDXIO17 Raider(s) // ⚠ call by a basestar router.post("/api/coordinates").handler

    { context -> // check data -> if null, don't move val computedX = context.bodyAsJson.getDouble("x") ?: x val computedY = context.bodyAsJson.getDouble("y") ?: y val computedXVelocity = context.bodyAsJson.getDouble("xVelocity") ?: xVelocity val computedYVelocity = context.bodyAsJson.getDouble("yVelocity") ?: yVelocity /* === updating record of the service === */ record?.metadata?.getJsonObject("coordinates") ?.put("x", computedX) ?.put("y",computedY) ?.put("xVelocity",computedXVelocity) ?.put("yVelocity",computedYVelocity) record?.metadata?.put("basestar", json {obj( "name:" to baseStar?.record?.name, "color" to baseStar?.record?.metadata?.get("color") )}) discovery?.update(record, {asyncUpdateResult -> }) context .response().putHeader("content-type", "application/json;charset=UTF-8") .end(json {obj( "message" to "", "x" to computedX, "y" to computedY )}.toString()) }
  87. #BSGTHEPLAN #BDXIO17 Raider(s) // ⚠ call by a basestar router.post("/api/coordinates").handler

    { context -> // check data -> if null, don't move val computedX = context.bodyAsJson.getDouble("x") ?: x val computedY = context.bodyAsJson.getDouble("y") ?: y val computedXVelocity = context.bodyAsJson.getDouble("xVelocity") ?: xVelocity val computedYVelocity = context.bodyAsJson.getDouble("yVelocity") ?: yVelocity /* === updating record of the service === */ record?.metadata?.getJsonObject("coordinates") ?.put("x", computedX) ?.put("y",computedY) ?.put("xVelocity",computedXVelocity) ?.put("yVelocity",computedYVelocity) record?.metadata?.put("basestar", json {obj( "name:" to baseStar?.record?.name, "color" to baseStar?.record?.metadata?.get("color") )}) discovery?.update(record, {asyncUpdateResult -> }) context .response().putHeader("content-type", "application/json;charset=UTF-8") .end(json {obj( "message" to "", "x" to computedX, "y" to computedY )}.toString()) }
  88. #BSGTHEPLAN #BDXIO17 Raider CircuitBreaker

  89. #BSGTHEPLAN #BDXIO17 CircuitBreaker toc toc Penny ? toc toc Penny

    ? toc toc Penny ? ok j’arrĂȘte
  90. #BSGTHEPLAN #BDXIO17 Raider(s) | circuitbreaker /* === Define a circuit

    breaker === */ breaker = CircuitBreaker.create("bsg-circuit-breaker", vertx, CircuitBreakerOptions( maxFailures = 5, timeout = 20000, fallbackOnFailure = true, resetTimeout = 100000))
  91. #BSGTHEPLAN #BDXIO17 Raider /* === search for a baseStar ===

    */ searchAndSelectOneBaseStar()
  92. #BSGTHEPLAN #BDXIO17 Raider(s) fun searchAndSelectOneBaseStar() { /* === search for

    a baseStar in the discovery backend === */ discovery?.getRecords( {r -> r.metadata.getString("kind") == "basestar" && r.status == io.vertx.servicediscovery.Status.UP }, { asyncResult -> when { asyncResult.failed() -> { } // asyncResult.succeeded() -> { // val baseStarsRecords = asyncResult.result() // === choose randomly a basestar === baseStarsRecords.size.let { when(it) { 0 -> { searchAndSelectOneBaseStar()/* oh oh no basestar online ?!!! */ } else -> { val selectedRecord = baseStarsRecords.get(Random().nextInt(it)) subscribeToBaseStar(selectedRecord) // } } } } } } ) // ⬅ end of the discovery }
  93. #BSGTHEPLAN #BDXIO17 Raider(s) fun searchAndSelectOneBaseStar() { /* === search for

    a baseStar in the discovery backend === */ discovery?.getRecords( {r -> r.metadata.getString("kind") == "basestar" && r.status == io.vertx.servicediscovery.Status.UP }, { asyncResult -> when { asyncResult.failed() -> { } // asyncResult.succeeded() -> { // val baseStarsRecords = asyncResult.result() // === choose randomly a basestar === baseStarsRecords.size.let { when(it) { 0 -> { searchAndSelectOneBaseStar() /* oh oh no basestar online ?!!! */ } else -> { val selectedRecord = baseStarsRecords.get(Random().nextInt(it)) subscribeToBaseStar(selectedRecord) // } } } } } } ) // ⬅ end of the discovery }
  94. #BSGTHEPLAN #BDXIO17 Raider subscribeToBaseStar(selectedRecord) //

  95. #BSGTHEPLAN #BDXIO17 Raider(s) fun subscribeToBaseStar(selectedRecord: Record) { val serviceReference =

    discovery?.getReference(selectedRecord) val webClient = serviceReference?.getAs(WebClient::class.java) // === CIRCUIT BREAKER === try to register to the basestar breaker?.execute<String>({ future -> webClient?.post("/api/raiders")?.sendJson(json { obj("registration" to record?.registration )}, { baseStarResponse -> when { baseStarResponse.failed() -> { this.baseStar = null // remove the basestar future.fail(" ouch something bad happened") } baseStarResponse.succeeded() -> { println(" you found a basestar") val selectedBaseStar = BaseStar(selectedRecord, webClient) this.baseStar = selectedBaseStar // time to check the health of my basestar watchingMyBaseStar(selectedBaseStar) future.complete(" yesss!") } } }) })?.setHandler({ breakerResult -> }) }
  96. #BSGTHEPLAN #BDXIO17 Raider(s) fun subscribeToBaseStar(selectedRecord: Record) { val serviceReference =

    discovery?.getReference(selectedRecord) val webClient = serviceReference?.getAs(WebClient::class.java) // === CIRCUIT BREAKER === try to register to the basestar breaker?.execute<String>({ future -> webClient?.post("/api/raiders")?.sendJson(json { obj("registration" to record?.registration )}, { baseStarResponse -> when { baseStarResponse.failed() -> { this.baseStar = null // remove the basestar future.fail(" ouch something bad happened") } baseStarResponse.succeeded() -> { println(" you found a basestar") val selectedBaseStar = BaseStar(selectedRecord, webClient) this.baseStar = selectedBaseStar // time to check the health of my basestar watchingMyBaseStar(selectedBaseStar) future.complete(" yesss!") } } }) })?.setHandler({ breakerResult -> }) }
  97. #BSGTHEPLAN #BDXIO17 Raider(s) fun subscribeToBaseStar(selectedRecord: Record) { val serviceReference =

    discovery?.getReference(selectedRecord) val webClient = serviceReference?.getAs(WebClient::class.java) // === CIRCUIT BREAKER === try to register to the basestar breaker?.execute<String>({ future -> webClient?.post("/api/raiders")?.sendJson(json { obj("registration" to record?.registration )}, { baseStarResponse -> when { baseStarResponse.failed() -> { this.baseStar = null // remove the basestar future.fail(" ouch something bad happened") } baseStarResponse.succeeded() -> { println(" you found a basestar") val selectedBaseStar = BaseStar(selectedRecord, webClient) this.baseStar = selectedBaseStar // time to check the health of my basestar watchingMyBaseStar(selectedBaseStar) future.complete(" yesss!") } } }) })?.setHandler({ breakerResult -> }) } ⚠⚠⚠
  98. #BSGTHEPLAN #BDXIO17 Raider // time to check the health of

    my basestar watchingMyBaseStar(selectedBaseStar)
  99. #BSGTHEPLAN #BDXIO17 Raider(s) fun watchingMyBaseStar(baseStar: BaseStar) { // oh oh

    a B vertx.setPeriodic(1000, { timerId -> baseStar.client.get("/health").send { asyncGetRes -> when { asyncGetRes.failed() -> { record?.metadata?.getJsonObject("coordinates") ?.put("xVelocity",0) ?.put("yVelocity",0) // btw, you never stop in space discovery?.update(record, {asyncUpdateResult -> println("${record?.name} I'm alone ?") // time to search a new basestar searchAndSelectOneBaseStar() vertx.setTimer(3000, { id -> vertx.cancelTimer(timerId) }) }) } asyncGetRes.succeeded() -> { // === all is fine === } } } }) }
  100. #BSGTHEPLAN #BDXIO17 Raider(s) fun watchingMyBaseStar(baseStar: BaseStar) { // oh oh

    a B vertx.setPeriodic(1000, { timerId -> baseStar.client.get("/health").send { asyncGetRes -> when { asyncGetRes.failed() -> { record?.metadata?.getJsonObject("coordinates") ?.put("xVelocity",0) ?.put("yVelocity",0) // btw, you never stop in space discovery?.update(record, {asyncUpdateResult -> println("${record?.name} I'm alone ?") // time to search a new basestar searchAndSelectOneBaseStar() vertx.setTimer(3000, { id -> vertx.cancelTimer(timerId) }) }) } asyncGetRes.succeeded() -> { // === all is fine === } } } }) }
  101. #BSGTHEPLAN #BDXIO17 Raider(s) fun watchingMyBaseStar(baseStar: BaseStar) { // oh oh

    a B vertx.setPeriodic(1000, { timerId -> baseStar.client.get("/health").send { asyncGetRes -> when { asyncGetRes.failed() -> { record?.metadata?.getJsonObject("coordinates") ?.put("xVelocity",0) ?.put("yVelocity",0) // btw, you never stop in space discovery?.update(record, {asyncUpdateResult -> println("${record?.name} I'm alone ?") // time to search a new basestar searchAndSelectOneBaseStar() vertx.setTimer(3000, { id -> vertx.cancelTimer(timerId) }) }) } asyncGetRes.succeeded() -> { // === all is fine === } } } }) }
  102. #BSGTHEPLAN #BDXIO17 Raider(s) fun watchingMyBaseStar(baseStar: BaseStar) { // oh oh

    a B vertx.setPeriodic(1000, { timerId -> baseStar.client.get("/health").send { asyncGetRes -> when { asyncGetRes.failed() -> { record?.metadata?.getJsonObject("coordinates") ?.put("xVelocity",0) ?.put("yVelocity",0) // btw, you never stop in space discovery?.update(record, {asyncUpdateResult -> println("${record?.name} I'm alone ?") // time to search a new basestar searchAndSelectOneBaseStar() vertx.setTimer(3000, { id -> vertx.cancelTimer(timerId) }) }) } asyncGetRes.succeeded() -> { // === all is fine === } } } }) }
  103. #BSGTHEPLAN #BDXIO17 RĂ©capitulatif BaseStar JAVA BaseStar JAVA BaseStar JAVA REDIS

    BaseStar JAVA GET http://localhost:808N/api/raiders POST http://localhost:808N/api/raiders GET http://localhost:808N/health BSG monitor SCALA GET http://localhost:8080/api/raiders BSG map JS http://localhost:7070 BaseStar JAVA Raider KOTLIN Raider KOTLIN Raider GROOVY Raider GROOVY POST http://localhost:909N/api/coordinates Raider GROOVY Raider KOTLIN Raider GROOVY GET http://localhost:909N/health POST http://localhost:808N/api/raiders POST http://localhost:909N/api/coordinates GET http://localhost:808N/health
  104. #BSGTHEPLAN #BDXIO17 checklist ✅ DĂ©marrer les BaseStars ✅ cf Base

    Redis - MEDIS ✅ DĂ©marrer Redis ✅ DĂ©marrer BSG Monitor ✅ DĂ©marrer BSG Map ✅ DĂ©marrer Raiders (kotlin) ✅ Tuer des BaseStars
  105. #BSGTHEPLAN #BDXIO17 Faker Raider(s)

  106. #BSGTHEPLAN #BDXIO17 ServiceDiscoveryRestEndpoint.java // use me with other microservices ServiceDiscoveryRestEndpoint.create(router,

    discovery); http://localhost:8081/discovery #BSGTHEPLAN #BDXIO17
  107. #BSGTHEPLAN #BDXIO17 checklist ✅ DĂ©marrer les BaseStars ✅ cf Base

    Redis - MEDIS ✅ DĂ©marrer Redis ✅ DĂ©marrer BSG Monitor ✅ DĂ©marrer BSG Map ✅ DĂ©marrer Raiders (kotlin) ✅ Tuer des BaseStars ✅ http://localhost:8080/discovery ✅ DĂ©marrer Fake-Raider (Node) ✅ DĂ©marrer Raiders (groovy) ✅ Ajouter des BaseStars
  108. #BSGTHEPLAN #BDXIO17 Conclusion(s) - Remarques - Perspectives #BSGTHEPLAN #BDXIO17

  109. #BSGTHEPLAN #BDXIO17 Perspectives ‱ DĂ©ploiement sur le cloud, j’ai eu

    des surprises / API Management ‱ Remettre Ă  plat mon code | Refactoring ‱ Ecrire un autre ServiceDiscoveryBackend (Redis PubSub, MQTT, 
) ‱ Utilisation d’un reverse proxy (peut-ĂȘtre) ‱ Ajouter les 12 colonies dans la dĂ©mo ‱ SĂ©curitĂ© - AuthentiïŹcation https://github.com/botsgarden/vertx-service-discovery-backend-redisson
  110. #BSGTHEPLAN #BDXIO17 Merci D ‱ Vous ‱ BDX.io ‱ ClĂ©ment

    EscoïŹƒer | Julien Viet | Julien Ponge
  111. #BSGTHEPLAN #BDXIO17 Questions https://github.com/the-plan