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

Applications réactives avec Eclipse Vert.x

Cb52062fbd7e159b54e3c298d622fe72?s=47 Julien Viet
December 13, 2017
180

Applications réactives avec Eclipse Vert.x

Cb52062fbd7e159b54e3c298d622fe72?s=128

Julien Viet

December 13, 2017
Tweet

Transcript

  1. Applications réactives avec Eclipse Vert.x Paris JUG

  2. Julien Viet Open source developer for 15+ years Current @vertx_project

    lead Principal software engineer at Marseille Java User Group Leader https://www.julienviet.com/ http://github.com/vietj @julienviet  https://www.mixcloud.com/cooperdbi/
  3. Outline ✓ Reactive? Vert.x? ✓ Foundations ✓ High performance networking

    ✓ Ecosystem
  4. Reactive? Vert.x?

  5. None
  6. Application

  7. Software Messages Requests Metrics Availability

  8. 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, Rx v2, Reactor, Vert.x Reactor, Reactive Spring, RxJava, Vert.x
  9. 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
  10. None
  11. Reactive foundations

  12. Reactive foundations ✓ Concurrency model ✓ Scalability model

  13. while (isRunning) { String line = bufferedReader.readLine(); switch (line.substring(0, 4))

    { case "ECHO": bufferedWriter.write(line); break !// !!... !// other cases (!!...) !// !!... default: bufferedWriter.write("Unknown command"); } }
  14. x 1000 = Ǚ

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

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

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

  18. Vertx vertx = Vertx.vertx(); // Create a Vert.x context associated

    with an event loop Context context = vertx.getOrCreateContext(); // Execute a task on the event loop context.runOnContext(v -> { // Create an HTTP server running on this context’s event loop HttpServer server = vertx.createHttpServer(); server.requestHandler(request -> { request.response().end("Hello World"); }).listen(8080); }); System.in.read(); // Close all resources vertx.close();
  19.  Verticles public class HttpVerticle extends AbstractVerticle { public static

    void main(String[] args) { Vertx vertx = Vertx.vertx(); vertx.deployVerticle(Server.class.getName()); System.in.read(); vertx.close(); } @Override public void init(Vertx vertx, Context context) { // Associates this verticle with // its deployment context super.init(vertx, context); } @Override public void start() throws Exception { HttpServer server = vertx.createHttpServer(); server.requestHandler(request -> { request .response() .end("Hello World"); }).listen(8080); } }
  20. Configuration Network events come from event loop threads Verticle Deploy

    Deploy
  21. Simplified concurrency model public class ChatVerticle extends AbstractVerticle { private

    Set<ServerWebSocket> webSockets = new HashSet<>(); @Override public void start() throws Exception { HttpServer server = vertx.createHttpServer(); server.websocketHandler(webSocket -> { webSocket.textMessageHandler(msg -> { webSockets.forEach(other -> other.writeTextMessage(msg)); }); webSocket.closeHandler(v -> webSockets.remove(webSocket)); webSockets.add(webSocket); }).listen(8080); } }
  22. Worker thread pool Blocking task executeBlocking Result

  23. “Regular verticle” (same event event-loop thread) Worker verticle (1 worker

    thread) Multi-thread worker verticle Worker pool
  24. Deployment model Vertx vertx = Vertx.vertx(); vertx.deployVerticle(HttpVerticle.class.getName(), new DeploymentOptions() .setInstances(3));

    Deploys 3 instances 3 event loop 1. bind the port 2. add event loop 3. add event loop
  25. None
  26. Deployment model Vertx vertx = Vertx.vertx(); // Deploy 5 instances

    on 5 event loops vertx.deployVerticle(HttpVerticle.class.getName(), new DeploymentOptions() .setInstances(5)); // The database verticle uses // deploy 2 instances on 2 event loops vertx.deployVerticle(DatabaseVerticle.class.getName(), new DeploymentOptions() .setInstances(2));
  27. High performance networking

  28. Performance ✓ Building bottom up ✓ Non blocking IO ✓

    Reactive back-pressure
  29. Pay the right price ✓ Tiny footprint ✓ Do one

    thing and do it well ✓ Does not solve other (non) problems such as classloading or IoC ✓ Modular set of extensions
  30. Non-blocking IO benefits ✓ Handle many connections with a few

    threads - focus on protocol concurrency - minimize system calls - more efficient for pipelined/multiplexed protocols
  31. Non-blocking IO benefits ✓ Get away from thread pools -

    removes unnecessary bottlenecks - easier capacity planning - focus on protocol concurrency
  32. Non-blocking IO benefits ✓ Gracefully handle slow connection - remain

    responsive - don’t impact other connections
  33. Networking/messaging with Vert.x ✓ Vert.x Core - TCP, HTTP/1, HTTP/2,

    WebSocket, UDP, DNS ✓ Vert.x Web - SockJS ✓ MQTT ✓ AMQP ✓ gRPC
  34. Typical HTTP server MongoClient client = MongoClient.createNonShared(vertx, getConfig());
 HttpServer server

    = vertx.createHttpServer(); 
 server.requestHandler(request -> {
 if (request.path().equals("/document")) {
 client.findOne("docs", QUERY, fieldsOf(request), ar -> {
 if (ar.succeeded()) {
 String json = ar.result().encode();
 request.response().end(json);
 } else {
 request.response().setStatusCode(500).end();
 }
 });
 } else { /* … */ }
 });
 
 server.listen(8080);
  35. Blocking server Backend Workers

  36. Blocking server Backend Workers

  37. Blocking server Backend Workers

  38. Blocking server Backend Workers

  39. Blocking server Backend Workers

  40. Blocking server Backend Workers

  41. Blocking server Backend Workers

  42. Non-blocking server Backend Event Loop Requests Responses

  43. Non-blocking server Backend Event Loop Requests Responses

  44. Non-blocking server Backend Event Loop Requests Responses

  45. Non-blocking server Backend Event Loop Requests Responses

  46. Non-blocking server Backend Event Loop Requests Responses

  47. Non-blocking server Backend Event Loop Requests Responses

  48. Message passing on the event bus

  49. Http server verticle Database client verticle  ?

  50. Http server verticle Database client verticle  Event Bus “Details

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

    for user 1234?” Send to “user.db” Consume from “user.db” ×3 ×10
  52. Http server verticle Database client verticle  Event Bus “Details

    for user 1234?” “{data}” ×3 ×10
  53. Asynchronous messaging “foo.bar”, “foo-bar”, “foo/bar”, … Point to point (with

    possible response back) Publish / subscribe
  54. Distributed across Vert.x nodes Hazelcast, Ignite, Infinispan, … TCP bridge

    interface Go, Python, C, JavaScript, Swift, C#, … SockJS bridge Seamless frontend / backend messaging
  55. Headers DeliveryOptions (e.g., timeouts) Body Address Reply address

  56. “Primitive” types String, int, double, … JSON Object/Array Polyglot applications,

    clean boundaries Custom codecs For advanced usages
  57. 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"); } }); });
  58. Dealing with asynchronous events

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

    (codegen) (codegen) (codegen) (codegen)
  60. 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”
  61. jdbc.rxGetConnection().flatMap(conn !-> { !// Now chain some statements using flatmap

    composition Single<ResultSet> resa = conn.rxUpdate("CREATE TABLE test(col VARCHAR(20))") .flatMap(result !-> conn.rxUpdate("INSERT INTO test (col) VALUES ('val1')")) .flatMap(result !-> conn.rxUpdate("INSERT INTO test (col) VALUES ('val2')")) .flatMap(result !-> conn.rxQuery("SELECT * FROM test")); return resa.doAfterTerminate(conn!::close); }).subscribe(resultSet !-> { !// Subscribe to the final result System.out.println("Results : " + resultSet.getRows()); }, err !-> { System.out.println("Database problem"); err.printStackTrace(); });
  62. try (SQLConnection conn = awaitResult(jdbc!::getConnection)) { !// Create a table

    Void v = awaitResult(h !-> conn.execute("CREATE TABLE test(col VARCHAR(20))", h)); !// Insert some stuff for (int i = 0; i < 10; i!++) { int ii = i; UpdateResult res = awaitResult(h !-> conn.update("INSERT INTO test (col) VALUES ('val" + ii + "')", h)); System.out.println("Rows updated: " + res.getUpdated()); } !// Select the results ResultSet res = awaitResult(h !-> conn.query("SELECT * FROM test", h)); System.out.println("Selected " + res.getNumRows() + " results"); res.getResults().forEach(System.out!::println); }
  63. val consumer = vertx.eventBus().localConsumer<String>("a.b.c") consumer.handler { message "-> println("Consumer received:

    ${message.body()}") message.reply("pong") } !// Wait until the consumer has properly registered asyncResult<Void> { h "-> consumer.completionHandler(h) } !// Send a message and wait for a reply val reply = asyncResult<Message<String!>> { h "-> vertx.eventBus().send("a.b.c", "ping", h) } println("Reply received: ${reply.body()}")
  64. Reactive Programming with Vert.x and RxJava

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

    coordination of events Makes most sense with many sources of events
  66. Motivation Future<List<T!>> is not appropriate Dealing with latencies Functional programming

    influence
  67. RxJava 1 vs RxJava 2 Better raw performances Based on

    reactive-streams Null values forbidden More reactive types Observable / Flowable Single / Maybe / Completable
  68. Event push subscribe ➊ ➋push Observer Observable

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

    { ➊
 } ➌
 } catch (Throwable e) { ➋
 } observable.subscribe(item -> {
 ➊ // onNext
 }, error -> {
 ➋ // onError
 }, () -> {
 ➌ // onCompleted
 });
  70. RxJava 1 types Reactive Completable Single<T> Observable<T> Interactive void Optional<T>

    Iterable<T>
  71. RxJava 2 types Reactive Completable Maybe<T> Single<T> Observable<T> Interactive void

    Optional<T> T Iterable<T>
  72. None
  73. None
  74. None
  75. None
  76. Rxified APIs Each API type (annotated with @VertxGen) has its

    prefix io.vertx replaced by io.vertx.rxjava io.vertx.core.Vertx io.vertx.rxjava.Vertx etc…
  77. Rxified Handler<AsyncResult> void listen(int port, Handler<AsyncResult<HttpServer>> ar)
 
 Single<HttpServer> rxListen(int

    port);
  78. (demo) RxJava

  79. Outro

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

  81. 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)
  82. https:!//youtu.be/ZkWsilpiSqw Applications réactives avec Eclipse Vert.x Building Reactive Microservices in

    Java https:!//goo.gl/ep6yB9 https:!//youtu.be/ApGNp4uHKdY Microservices réactifs avec Eclipse Vert.x et Kubernetes Guide to async programming with Vert.x for Java developers https:!//goo.gl/AcWW3A