Reactive Web Applications: Springone2Gx

You might also like

Download as pdf or txt
Download as pdf or txt
You are on page 1of 52

SPRINGONE2GX

WASHINGTON, DC

Reactive Web Applications


Stephane Maldini
Rossen Stoyanchev

Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/
About the Speakers
• Stephane Maldini
• Reactor Project Lead
• Reactive Streams Spec contributor

• Rossen Stoyanchev
• Spring Framework committer
• Spring MVC
• WebSocket messaging (STOMP, SockJS)

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 2
Why are you here ?

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 3
What is Reactive ?

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 4
Why Non Blocking Matters ?

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 5
Non Blocking = Faster ?

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 6
Non Blocking = Internet Scale ?

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 7
Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 8
Reactive Web App Stack

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 9
Servlet 3.0 Async Requests
• Async HTTP requests have been possible since Servlet 3.0

• Essentially: the ability to get off the Servlet container thread


• originated from Jetty continuations, CometD, etc.

• “Live” data in web apps


• e.g. HTTP streaming, long polling

• Reduce burden on server thread pool


• scatter-gather, external REST APIs, etc

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 10
Servlet 3.0 Async Requests: the bottom line
• A bit quirky, Servlet API wasn’t built for async

• Complex to grasp in its entirety + comes with some caveats


• e.g. lack of notification when client goes away

• Spring MVC provides full support for Servlet 3 async requests


• alleviates most concerns

• Effectively async can be introduced into existing applications


• … and ecosystem of libraries !

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 11
Servlet 3.1 Non-Blocking I/O
• Read and write without blocking

• Register ReadListener and WriteListener callbacks


• switches to non-blocking mode

• ServletInputStream and ServletOutputStream change behavior

• Must call isReady first before read() or write()


• if connection not ready (slow client), callback is scheduled

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 12
Servlet 3.1 Non-Blocking: the bottom line
• Carefully designed + it does provide non-blocking capability

• However not easy to use correctly, a number of pitfalls

• Many “innocent” looking parts of Servlet API may lead to blocking


• e.g. request.getParameters()

• For a good overview and perspective see Greg Wilkins’ talk


• ”Into the Wild with Servlet 3.1 Async I/O”

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 13
Reactive Streams Spec for the JVM
• Specification for non-blocking library interop
• governs exchange of data across async boundaries

• Collaborative effort
• Kaazing, Netflix, Pivotal, RedHat, Twiiter, Typesafe

• Momentum and growing ecosystem of libraries


• network, database, etc.

• On path to adoption in JDK 9 java.util.concurrent

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 14
Reactive Streams API

onSubscribe

request(n) Subscriber
Publisher Subscription cancel()

onNext*
(onError|onComplete)?

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 15
Reactive Back-Pressure
• A key part of Reactive Streams is back-pressure

• It’s a type of flow control

• Subscribers make requests for additional data

• Publishers abide and produce what has been requested

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 16
Reactive Streams for Network I/O

public interface ServerHttpRequest extends HttpRequest {

Publisher<byte[]> getBody();

public interface ServerHttpResponse extends HttpMessage {

Publisher<Void> writeWith(Publisher<byte[]> publisher);

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 17
Instead of...

public interface ServerHttpRequest extends HttpRequest {

InputStream getBody();

public interface ServerHttpResponse extends HttpMessage {

OutputStream getBody();

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 18
Reactive Streams over Servlet Runtime ?
• Servlet 3.1 provides the non-blocking capability

• Reactive Streams provides a non-blocking API with broad industry support

• A single Reactive Streams pipeline


• back-pressure through the layers (from DB to Web server)

• Jetty is actively investigating this very option

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 19
Reactive Streams and Servlet 4.0 ???
• It is under discussion in the expert group

• It would be great if it did happen

• Potential obstacle is the Java EE 8 - JDK 8 association

• Hopefully not a show-stopper since Reactive Streams is here today

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 20
Reactive Streams Over Netty
• Netty was designed from the ground up to be non-blocking

• Easy to translate to Reactive Streams semantics

• Two ongoing experiments


• RxNetty
• Reactor Net

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 21
Reactive Streams Network I/O
Akka HTTP, Vert.x, Ratpack, Reactor Net, RxNetty*

*(via RxJava-ReactiveStreams bridge)

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 22
Reactive
Web App Stack
Reactive Streams

Netty, Servlet 3.1

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 23
Web Framework
Reactive
Web App Stack
Reactive Streams

Netty, Servlet 3.1

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 24
Application

Web Framework
Reactive
Web App Stack
Reactive Streams

Netty, Servlet 3.1

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 25
HTTP
Reactive
Application Data
Streams
Broker

Web Framework
Reactive
Web App Stack
Reactive Streams

Netty, Servlet 3.1

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 26
HTTP
Application
? Reactive
Streams Data
Broker
?
Web Framework
API to compose
asynchronous
Reactive Streams
streams?
Netty, Servlet 3.1

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 27
Working with Streams
• Non-blocking services return Publisher<T> instead of <T>

• How do you attach further processing?

• Reactive Streams is a callback-based API


• becomes very nested quickly

• Need something more declarative


• it’s beyond the scope of Reactive Streams

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 28
Stream Operations
• Publisher represents a stream of data

• It’s natural to apply operations functional-style


• like the Java 8 Stream

• Need API for composing async logic


• rise above callbacks

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 29
Reactor Stream
• Project Reactor provides a Stream API

• Reactive Streams Publisher + composable operations

Streams.just('a' 'b' 'c')


.take(2)
.map(Character::toUpperCase)
.consume(System.out::println);

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 30
Reactive Extensions (Rx)
• Stream composition API based on Observer pattern
• originated at Microsoft, work by Erik Meijer

• Implemented for different languages -- RxJava, RxJS, Rx.NET, …

Observable.just('a', 'b', 'c')


.take(2)
.map(Character::toUpperCase)
.subscribe(System.out::println);

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 31
RxJava and Reactive Streams
• RxJava 1.x predates Reactive Streams and doesn’t implement it directly

• Very similar concepts, different names


• Observable-Observer vs Publisher-Subscriber

• RxJava supports “reactive pull” back-pressure

• RxJava 1.x - Reactive Streams bridge

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 32
Demo:

HeadFirst

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 33
RxNetty
• RxJava as the reactive bridge to Netty IO operations

• Immediate and embedded client/server for TCP and HTTP

• Decorating IO Read with rx.Observable and applying dynamic pull/push

• Decorating IO Write with rx.Subscriber and requesting more on flush

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 34
RxNetty … what’s up
• RxNetty has introduced Backpressure support in 0.5

• Powered by the backpressure protocol from RxJava

• Overall the API has been heavily lifted too


https://github.com/ReactiveX/RxNetty/wiki/0.5.x-FAQs

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 35
Reactor Net
• Reactive Streams as the reactive bridge to Netty and ZeroMQ IO operations

• Immediate and embedded client/server for TCP, UDP and HTTP

• Decorating IO Read with Publisher and applying dynamic pull/push

• Decorating IO Write with Subscriber and requesting more on flush

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 36
Member of the Reactor initiative
• Reactor is a maturing Reactive Streams suite of libraries

• As with a lot of the reactive libraries, observing a rapidly evolving set of API

• Precluded Reactive Streams specification work

• Now evolving and getting ready for Spring 5 Reactive story

projectreactor.io , github.com/reactor

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 37
Demo:

Back-Pressure

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 38
Async I/O with Reactive Streams
• Never block on Applications Queues :
Max(request) == Queue.capacity()

• Keep Reading : Any asynchronous handoff is non-blocking

• Make Writes Quicker : IO operation signals demand on availability

• Optimize hardware resources : Claim bounded memory and cpu

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 39
Reactive Read
One read implementation : Publisher stop-read

• Consume NIO Buffers only when requested

• request size is != bytes read

• Application stopping reads propagates back-pressure


• server buffers fill
• client buffers fill
• eventually throttles client

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 40
Reactive Write
One write implementation : Subscriber request after flush

• Request after flush indicates availability in write buffer

• Request size is != bytes written

• Write buffers filling naturally propagates back-pressure


• buffers fill
• no requests
• eventually throttles application

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 41
Serialization Concerns
• Subscription.request(n)is not absolute ( != bytes number )

• Decoding operations might produce one to many objects


• must match subscriber capacity

• Encoding operations might consume one to many byte chunks


• must match buffering capacity

• Available serialization libraries not built for chunked streams


• Jackson, Kryo, Protobuf, etc.

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 42
Demo:

Scatter-gather

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 43
Spring Reactive

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 44
Spring Reactive
• Experimental work for Spring Framework 5

• Non-blocking runtimes -- Netty, Jetty, Tomcat

• Reactive Streams over network I/O -- RxNetty, Reactor Net

• Spring web processing

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 45
Reactive Streams Publisher

@RequestMapping("/capitalize")
@ResponseBody
public Publisher<Person> capitalize(@RequestBody Publisher<Person> persons) {
// …
}

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 46
Reactor Stream

@RequestMapping("/capitalize")
@ResponseBody
public Stream<Person> capitalize(@RequestBody Stream<Person> persons) {
return persons.map(person -> {
person.setName(person.getName().toUpperCase());
return person;
});
}

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 47
RxJava Observable

@RequestMapping("/capitalize")
@ResponseBody
public Observable<Person> capitalize(@RequestBody Observable<Person> persons) {
return persons.map(person -> {
person.setName(person.getName().toUpperCase());
return person;
});
}

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 48
ReactiveX On the Client Side

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 49
RxJS
function() {
StreamService.connect("stream")
.flatMap(unpackCsv)
.subscribe(updateUI, logError, logComplete);
}

var unpackCsv = function (ev) {


return Rx.Observable.from(ev.data ? ev.data.split("\n") : [])
.filter(discardEmpty)
.map(csvToJson)
}

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 50
Demo:

RxJS and Ratpack

Unless otherwise indicated these slides are © 2013-2014 Pivotal Software Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 51
Learn More. Stay Connected.

@springcentral Spring.io/video

Thank You for Listening!


@smaldini / @rstoya05
Unless otherwise indicated, these slides are © 2013-2014 Pivotal Software, Inc. and licensed under a
Creative Commons Attribution-NonCommercial license: http://creativecommons.org/licenses/by-nc/3.0/ 52

You might also like