Slide 1

Slide 1 text

Services réactifs avec Vert.x et intégration avec Kotlin Julien Ponge — @jponge 2017/11/09 — Lyon Kotlin User Group

Slide 2

Slide 2 text

No content

Slide 3

Slide 3 text

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/

Slide 4

Slide 4 text

Outline ✓ Reactive? Vert.x? ✓ Vert.x core 101 ✓ Reactive extensions with RxJava 2 ✓ Kotlin coroutines and Vert.x

Slide 5

Slide 5 text

Reactive? Vert.x?

Slide 6

Slide 6 text

No content

Slide 7

Slide 7 text

Application

Slide 8

Slide 8 text

Software Messages Requests Metrics Availability

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

(demo) “Hello world in action”

Slide 13

Slide 13 text

Vert.x core — 101

Slide 14

Slide 14 text

Vert.x Concurrency Model

Slide 15

Slide 15 text

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"); } }

Slide 16

Slide 16 text

x 1000 = '

Slide 17

Slide 17 text

C1 “When you have a line of text, call C2” Something else with no blocking call either C2

Slide 18

Slide 18 text

Events Thread Event Loop

Slide 19

Slide 19 text

 2 event-loops per CPU core by default

Slide 20

Slide 20 text

 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() { }

Slide 21

Slide 21 text

) * Configuration ) ) Verticle Deploy Deploy

Slide 22

Slide 22 text

) Worker thread pool Blocking task + executeBlocking Result

Slide 23

Slide 23 text

Message passing on the event bus

Slide 24

Slide 24 text

) ) Http server verticle Database client verticle  ?

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

) . ) Http server verticle Database client verticle  Event Bus / . “Details for user 1234?” “{data}”

Slide 28

Slide 28 text

/ Asynchronous messaging “foo.bar”, “foo-bar”, “foo/bar”, … Point to point (with possible response back) Publish / subscribe

Slide 29

Slide 29 text

/ Distributed across Vert.x nodes Hazelcast, Ignite, Infinispan, … TCP bridge interface Go, Python, C, JavaScript, Swift, C#, … SockJS bridge Seamless frontend / backend messaging

Slide 30

Slide 30 text

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"); } }); });

Slide 31

Slide 31 text

MessageConsumer consumer = eventBus.consumer(“boilervroom.audiostream"); consumer.bodyStream().handler(buffer -> { if (!response.writeQueueFull()) { response.write(buffer); } }); Streams Backpressure, supports pausing / resuming / dropping

Slide 32

Slide 32 text

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

Slide 33

Slide 33 text

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); }

Slide 34

Slide 34 text

private void deletePage(Message 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()); } }); }

Slide 35

Slide 35 text

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…

Slide 36

Slide 36 text

@ProxyGen public interface WikiDatabaseService { // ( ...) @Fluent WikiDatabaseService savePage(int id, String markdown, Handler> resultHandler); @Fluent WikiDatabaseService deletePage(int id, Handler> 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

Slide 37

Slide 37 text

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()); } }); }

Slide 38

Slide 38 text

Dealing with asynchronous events

Slide 39

Slide 39 text

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”

Slide 40

Slide 40 text

Callbacks RxJava 1 + 2 Quasar (vertx-sync) Kotlin coroutines (core) (codegen)

Slide 41

Slide 41 text

Reactive Programming with Vert.x and RxJava Kotlin

Slide 42

Slide 42 text

RxJava Data and events flows Organising transformation of data and coordination of events Makes most sense with many sources of events

Slide 43

Slide 43 text

Push based subscribe ➊ ➋push Observer Observable

Slide 44

Slide 44 text

Iterable / Observable try {
 for (String item : it) { ➊
 } ➌
 } catch (Throwable e) { ➋
 } observable.subscribe(item -> {
 ➊ // onNext
 }, error -> {
 ➋ // onError
 }, () -> {
 ➌ // onCompleted
 });

Slide 45

Slide 45 text

0 0..1 0..n Reactive Completable Maybe Single Observable Flowable Interactive void T Iterable

Slide 46

Slide 46 text

No content

Slide 47

Slide 47 text

No content

Slide 48

Slide 48 text

No content

Slide 49

Slide 49 text

No content

Slide 50

Slide 50 text

Rxified Handler void listen(int port, Handler> ar)
 
 Single rxListen(int port);

Slide 51

Slide 51 text

(demo) RxJava

Slide 52

Slide 52 text

Kotlin coroutines (and Vert.x)

Slide 53

Slide 53 text

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

Slide 54

Slide 54 text

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

Slide 55

Slide 55 text

) Suspend ) Begin ) ) End Resume Coroutine life cycle

Slide 56

Slide 56 text

Coroutines are confined to Vert.x event loop threads awaitResult and awaitEvent Channels from/to Vert.x streams Integrates with the coroutine ecosystem Coroutines for Vert.x

Slide 57

Slide 57 text

(demo) Coroutines with and without Vert.x

Slide 58

Slide 58 text

Outro

Slide 59

Slide 59 text

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

Slide 60

Slide 60 text

No content

Slide 61

Slide 61 text

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)

Slide 62

Slide 62 text

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