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

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

50a17cd98aab2cc4d8e144741e11b1b7?s=47 Julien Ponge
November 09, 2017

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

Lyon Meetup User Group, November 2017

50a17cd98aab2cc4d8e144741e11b1b7?s=128

Julien Ponge

November 09, 2017
Tweet

Transcript

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

    — @jponge 2017/11/09 — Lyon Kotlin User Group
  2. None
  3. 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/
  4. Outline ✓ Reactive? Vert.x? ✓ Vert.x core 101 ✓ Reactive

    extensions with RxJava 2 ✓ Kotlin coroutines and Vert.x
  5. Reactive? Vert.x?

  6. None
  7. Application

  8. Software Messages Requests Metrics Availability

  9. 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
  10. 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
  11. None
  12. (demo) “Hello world in action”

  13. Vert.x core — 101

  14. Vert.x Concurrency Model

  15. 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"); } }
  16. x 1000 = '

  17. C1 “When you have a line of text, call C2”

    Something else with no blocking call either C2
  18. Events Thread Event Loop

  19.  2 event-loops per CPU core by default

  20.  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() { }
  21. ) * Configuration ) ) Verticle Deploy Deploy

  22. ) Worker thread pool Blocking task + executeBlocking Result

  23. Message passing on the event bus

  24. ) ) Http server verticle Database client verticle  ?

  25. ) . ) Http server verticle Database client verticle 

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

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

    Event Bus / . “Details for user 1234?” “{data}”
  28. / Asynchronous messaging “foo.bar”, “foo-bar”, “foo/bar”, … Point to point

    (with possible response back) Publish / subscribe
  29. / Distributed across Vert.x nodes Hazelcast, Ignite, Infinispan, … TCP

    bridge interface Go, Python, C, JavaScript, Swift, C#, … SockJS bridge Seamless frontend / backend messaging
  30. 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"); } }); });
  31. MessageConsumer<Buffer> consumer = eventBus.consumer(“boilervroom.audiostream"); consumer.bodyStream().handler(buffer -> { if (!response.writeQueueFull()) {

    response.write(buffer); } }); Streams Backpressure, supports pausing / resuming / dropping
  32. 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
  33. 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); }
  34. 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()); } }); }
  35. 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…
  36. @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
  37. 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()); } }); }
  38. Dealing with asynchronous events

  39. 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”
  40. Callbacks RxJava 1 + 2 Quasar (vertx-sync) Kotlin coroutines (core)

    (codegen)
  41. Reactive Programming with Vert.x and RxJava Kotlin

  42. RxJava Data and events flows Organising transformation of data and

    coordination of events Makes most sense with many sources of events
  43. Push based subscribe ➊ ➋push Observer Observable

  44. Iterable / Observable try {
 for (String item : it)

    { ➊
 } ➌
 } catch (Throwable e) { ➋
 } observable.subscribe(item -> {
 ➊ // onNext
 }, error -> {
 ➋ // onError
 }, () -> {
 ➌ // onCompleted
 });
  45. 0 0..1 0..n Reactive Completable Maybe<T> Single<T> Observable<T> Flowable<T> Interactive

    void T Iterable<T>
  46. None
  47. None
  48. None
  49. None
  50. Rxified Handler<AsyncResult> void listen(int port, Handler<AsyncResult<HttpServer>> ar)
 
 Single<HttpServer> rxListen(int

    port);
  51. (demo) RxJava

  52. Kotlin coroutines (and Vert.x)

  53. 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
  54. 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
  55. ) Suspend ) Begin ) ) End Resume Coroutine life

    cycle
  56. 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
  57. (demo) Coroutines with and without Vert.x

  58. Outro

  59. Vert.x Awesome Vert.x Stack Vert.x Core

  60. None
  61. 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)
  62. 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