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

Reactive Ruby - building web apps with JRuby and Ratpack

Reactive Ruby - building web apps with JRuby and Ratpack

Slides for my talk about reactive Ruby and building high performant web apps with JRuby and Ratpack.io at the RUG::B meetup 2017/03.

Max Mulatz

March 02, 2017
Tweet

More Decks by Max Mulatz

Other Decks in Programming

Transcript

  1. max

  2. “So let's cut the bullshit.
 Reactive programming is programming with

    asynchronous data streams” - @andrestaltz- # The introduction to Reactive Programming you've been missing
  3. “non-blocking communication allows recipients to only consume resources while active,

    leading to less system overhead” - reactivemanifesto- # reactivemanifesto.org
  4. # Get evens and square each some_source .select { |x|

    x.even? } .map { |x| x * x } .subscribe { |x| puts x.to_s } # github.com/ReactiveX/RxRuby
  5. public class Main { public static void main(String... args) throws

    Exception { RatpackServer.start(server -> server .handlers(chain -> chain .get(ctx -> ctx.render("Hello World")) ) ); } } # ratpack.io/manual/current/launching.html#launching
  6. # github.com/klappradla/jruby_ratpack_examples/hello_world require 'java' require 'jruby/core_ext' require 'bundler/setup' Bundler.require java_import

    'ratpack.server.RatpackServer' RatpackServer.start do |server| server.handlers do |chain| chain.get do |ctx| ctx.render('Hello World from Ratpack / JRuby') end end end
  7. “A promise is a representation of a value which will

    become available later. Methods such as map(Function) […] allow a pipeline of “operations” to be specified, that the value will travel through as it becomes available.” -ratpack docs- # ratpack.io/manual/current/api/ratpack/exec/Promise.html
  8. # ratpack.io/manual/current/async.html#performing_blocking_operations_eg_io java_import 'ratpack.server.RatpackServer' java_import 'ratpack.exec.Blocking' require 'json' RatpackServer.start do

    |server| server.handlers do |chain| chain.get('music') do |ctx| Blocking .get { DB[:albums].all } .then { |data| ctx.render(JSON.dump(data))} end end end
  9. RatpackServer.start do |server| server.handlers do |chain| chain.get('music') do |ctx| Blocking

    .get { DB[:albums].all } .then { |data| ctx.render(JSON.dump(data))} end end end
  10. RatpackServer.start do |server| server.handlers do |chain| chain.get('music') do |ctx| Blocking

    .get { DB[:albums].all } .map { |data| JSON.dump(data) } .then { |data| ctx.render(data)} end end end
  11. class Server def self.run RatpackServer.start do |server| server.handlers do |chain|

    chain.all(RequestLogger.ncsa) chain.get('music', Handler::Music) chain.get('planets', Handler::Planets) chain.all(Handler::NotFound) end end end end # github.com/klappradla/jruby_ratpack_examples/http_example
  12. # github.com/klappradla/jruby_ratpack_examples/http_example module Handler class Base def self.handle(ctx) new(ctx).handle end

    def initialize(ctx) @ctx = ctx end attr_reader :ctx def handle raise NotImplementedError end end end
  13. # github.com/klappradla/jruby_ratpack_examples/http_example java_import 'ratpack.http.client.HttpClient' require_relative 'base' module Handler class Planets

    < Base URL = java.net.URI.new('http://swapi.co/api/planets') def handle ctx .get(HttpClient.java_class) .get(URL) .map { |resp| resp.get_body } .map { |body| body.get_text } .then { |data| render(data) } end private def render(data) resp = ctx.get_response header = 'application/json;charset=UTF-8' resp.send(header, data) end end end
  14. # github.com/klappradla/jruby_ratpack_examples/benchmarks # Sinatra Running 30s test @ http://localhost:5050 4

    threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 284.63ms 358.37ms 1.95s 85.07% Req/Sec 145.18 72.13 434.00 65.54% 16392 requests in 30.08s, 64.94MB read Socket errors: connect 0, read 0, write 0, timeout 72 Non-2xx or 3xx responses: 1 Requests/sec: 545.00 Transfer/sec: 2.16MB # Ratpack Running 30s test @ http://localhost:5050 4 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 150.36ms 228.64ms 1.86s 88.18% Req/Sec 338.10 129.48 710.00 71.18% 32746 requests in 30.08s, 127.09MB read Requests/sec: 1088.56 Transfer/sec: 4.22MB
  15. # github.com/klappradla/jruby_ratpack_examples/benchmarks # Sinatra Running 30s test @ http://localhost:5050 4

    threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 284.63ms 358.37ms 1.95s 85.07% Req/Sec 145.18 72.13 434.00 65.54% 16392 requests in 30.08s, 64.94MB read Socket errors: connect 0, read 0, write 0, timeout 72 Non-2xx or 3xx responses: 1 Requests/sec: 545.00 Transfer/sec: 2.16MB # Ratpack Running 30s test @ http://localhost:5050 4 threads and 100 connections Thread Stats Avg Stdev Max +/- Stdev Latency 150.36ms 228.64ms 1.86s 88.18% Req/Sec 338.10 129.48 710.00 71.18% 32746 requests in 30.08s, 127.09MB read Requests/sec: 1088.56 Transfer/sec: 4.22MB