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

Services réactifs avec Vert.x et intégration avec Kotlin

Julien Ponge
November 09, 2017

Services réactifs avec Vert.x et intégration avec Kotlin

Lyon Meetup User Group, November 2017

Julien Ponge

November 09, 2017
Tweet

More Decks by Julien Ponge

Other Decks in Programming

Transcript

  1. Services réactifs avec Vert.x et intégration avec Kotlin Julien Ponge

    — @jponge 2017/11/09 — Lyon Kotlin User Group
  2. Julien Ponge Maitre de Conférences “Delegated consultant to Red Hat”

    on Vert.x Eclipse Golo + extensive F/OSS background ! https://julien.ponge.org/ " @jponge # @jponge  https://www.mixcloud.com/hclcast/
  3. Outline ✓ Reactive? Vert.x? ✓ Vert.x core 101 ✓ Reactive

    extensions with RxJava 2 ✓ Kotlin coroutines and Vert.x
  4. Reactive systems Reactive streams Reactive programming Reactive “Responding to stimuli”

    Manifesto, Actor, Messages Resilience, Elasticity, Scalability, Asynchronous, non-blocking Data flow Back-pressure Non-blocking Data flow Events, Observable Spreadsheets Akka, Vert.x Akka Streams, RxJava, Reactor, Vert.x Reactor, Reactive Spring, RxJava, Vert.x
  5. Eclipse Vert.x Open source project started in 2012 Eclipse /

    Apache licensing A toolkit for building reactive applications for the JVM 7K ⋆ on & Built on top of ! https://vertx.io " @vertx_project
  6. while (isRunning) { String line = bufferedReader.readLine(); switch (line.substring(0, 4))

    { case "ECHO": bufferedWriter.write(line); break // ... // other cases ( ...) // ... default: bufferedWriter.write("UNKW Unknown command"); } }
  7. C1 “When you have a line of text, call C2”

    Something else with no blocking call either C2
  8.  Verticles ) ) ) public class SomeVerticle extends AbstractVerticle

    { @Override public void start() throws Exception { } @Override public void stop() throws Exception { } } class SomeVerticle : AbstractVerticle() { override fun start() { } override fun stop() { } } exports.vertxStart = function() { } exports.vertxStop = function() { }
  9. ) . ) Http server verticle Database client verticle 

    Event Bus / “Details for user 1234?” Send to “user.db”
  10. ) . ) Http server verticle Database client verticle 

    Event Bus / “Details for user 1234?” Send to “user.db” Consume from “user.db”
  11. ) . ) Http server verticle Database client verticle 

    Event Bus / . “Details for user 1234?” “{data}”
  12. / Distributed across Vert.x nodes Hazelcast, Ignite, Infinispan, … TCP

    bridge interface Go, Python, C, JavaScript, Swift, C#, … SockJS bridge Seamless frontend / backend messaging
  13. EventBus eb = vertx.eventBus(); eb.consumer("ping-address", message -> { System.out.println("Received message:

    " + message.body()); message.reply("pong!"); }); EventBus eb = vertx.eventBus(); vertx.setPeriodic(1000, v -> { eb.send("ping-address", "ping!", reply -> { if (reply.succeeded()) { System.out.println("Received reply " + reply.result().body()); } else { System.out.println("No reply"); } }); });
  14. const eventBus = new EventBus("/eventbus") traktorIn.addListener("controlchange", 5, (event) => {

    eventBus.publish("boilervroom.vu-meter", { type: "volume-level", value: event.value }) }) eventBus.publish("boilervroom.fromtraktor", { type: "filter", number: 1, value: (event.value !== 0) }) Event Bus
  15. switch (message.headers().get("action")) { case "all-pages": fetchAllPages(message); break; case "get-page": fetchPage(message);

    break; case "create-page": createPage(message); break; case "save-page": savePage(message); break; case "delete-page": deletePage(message); break; default: message.fail(ErrorCodes.BAD_ACTION.ordinal(), "Bad action: " + action); }
  16. private void deletePage(Message<JsonObject> message) { dbClient.getConnection(car -> { if (car.succeeded())

    { SQLConnection connection = car.result(); JsonArray data = new JsonArray().add(message.body().getString("id")); connection.updateWithParams(sqlQueries.get(SqlQuery.DELETE_PAGE), data, res -> { connection.close(); if (res.succeeded()) { message.reply(new JsonObject().put("result", "ok")); } else { reportQueryError(message, res.cause()); } }); } else { reportQueryError(message, car.cause()); } }); }
  17. switch (message.headers().get("action")) { case "all-pages": fetchAllPages(message); break; case "get-page": fetchPage(message);

    break; case "create-page": createPage(message); break; case "save-page": savePage(message); break; case "delete-page": deletePage(message); break; default: message.fail(ErrorCodes.BAD_ACTION.ordinal(), "Bad action: " + action); } 0 If lots of actions…
  18. @ProxyGen public interface WikiDatabaseService { // ( ...) @Fluent WikiDatabaseService

    savePage(int id, String markdown, Handler<AsyncResult<Void >> resultHandler); @Fluent WikiDatabaseService deletePage(int id, Handler<AsyncResult<Void >> resultHandler); static WikiDatabaseService createProxy(Vertx vertx, String address) { return new WikiDatabaseServiceVertxEBProxy(vertx, address); } // ( ...) } Proxy + handler source code will be generated Parameters from a JSON document Handlers for replies Generated proxy
  19. dbService = WikiDatabaseService.createProxy(vertx, "wikidb.queue"); private void pageDeletionHandler(RoutingContext context) { dbService.deletePage(Integer.valueOf(context.request().getParam("id")),

    reply -> { if (reply.succeeded()) { context.response().setStatusCode(303); context.response().putHeader("Location", "/"); context.response().end(); } else { context.fail(reply.cause()); } }); }
  20. foo.a(1, res1 -> { if (res1.succeeded()) { bar.b("abc", 1, res2

    -> { if (res.succeeded()) { baz.c(res3 -> { dosomething(res1, res2, res3, res4 -> { // (...) }); }); } }); } }); “Callback hell”
  21. RxJava Data and events flows Organising transformation of data and

    coordination of events Makes most sense with many sources of events
  22. Iterable / Observable try {
 for (String item : it)

    { ➊
 } ➌
 } catch (Throwable e) { ➋
 } observable.subscribe(item -> {
 ➊ // onNext
 }, error -> {
 ➋ // onError
 }, () -> {
 ➌ // onCompleted
 });
  23. Coroutines are computer-program components that generalise subroutines for non-preemptive multitasking,

    by allowing multiple entry points for suspending and resuming execution at certain locations. “ ” — https://en.wikipedia.org/wiki/Coroutine
  24. Suspending lambdas and functions (suspend keyword) Compiler work for suspending

    functions (state machines…) Low-level library: kotlin.coroutines create / start / suspend / intrinsics sequence and iterator generators (think Python, Golo, etc) High-level library: kotlinx.coroutines core primitives (launch, async, select, delay, …) reactive, UI, CompletableFuture, etc Kotlin Coroutines
  25. Coroutines are confined to Vert.x event loop threads awaitResult<T> and

    awaitEvent<T> Channels from/to Vert.x streams Integrates with the coroutine ecosystem Coroutines for Vert.x
  26. Unified end-to-end reactive model + ecosystem (not just APIs…) For

    all kinds of distributed applications (even the small-scale ones) Flexible toolkit, not a framework (your needs, your call)
  27. https: //youtu.be/ZkWsilpiSqw 1 Applications réactives avec Eclipse Vert.x 2 Building

    Reactive Microservices in Java https: //goo.gl/ep6yB9 2 Guide to async programming with Vert.x for Java developers https: //goo.gl/AcWW3A 3 Kotlin Slack — #vertx