4. Reactor — Housekeeping
!
• Tweet questions during the presentation
– @ProjectReactor
!
• Stop us anywhere if you have a question
– There are no stupid questions, only stupid answers!
@glaforge — @smaldini / #DV13-rtweb
!4
6. Reactor — Reactive Architecture ?
• A good description is available on:
http://www.reactivemanifesto.org/
!
• Functional Programming helps as it is stimulus based by nature
!
• Groovy is a perfect candidate:
Closures and DSL are first class citizen
!
• Reactor completes the picture by providing abstractions
@glaforge — @smaldini / #DV13-rtweb
!6
8. Reactor — Dealing with performances
• Actors solve the locking and context switching issues
by becoming state boxes
• One thread assigned per consumer
• One thread will ever access a property
• Non Blocking Programming solves thread creation and
waiting issues by delaying logic
• Callback will be executed when possible (Lazy)
• Reallocate the blocking time to process something else
@glaforge — @smaldini / #DV13-rtweb
!8
9. Reactor — LMAX Disruptor and Ring Buffer
• LMAX Disruptor deals with message passing issues
• Based on a Ring Buffer structure
• “Mechanical Sympathy” in Disruptor
!
• http://lmax-exchange.github.com/disruptor/files/
Disruptor-1.0.pdf
• http://mechanitis.blogspot.co.uk/2011/06/dissecting-disruptorwhats-so-special.html
@glaforge — @smaldini / #DV13-rtweb
!9
12. Reactor — In love with Disruptor
• Reactor best performances are derived from LMAX Disruptor
!
• LMAX Disruptor can be considered
as an evolution of the Actor Model:
!
• Still avoid locking and deals with context switching
• Producer/Consumer decoupled
• Add Pipelining, Batching and more
@glaforge — @smaldini / #DV13-rtweb
!12
13. Reactor — A foundation part of Spring IO
@glaforge — @smaldini / #DV13-rtweb
!13
14. Reactor — What is it?
!
• Reactor is a distillation of other libraries and best-practices
– Elements of other patterns and libraries
surface throughout Reactor's abstractions
!
• http://stackoverflow.com/questions/16595393/akka-or-reactor
@glaforge — @smaldini / #DV13-rtweb
!14
15. Reactor — What can I build with it?
• Reactor applications are reactive
– Reactive Extensions in .NET
– Netflix RxJava
– Observer pattern
!
• Reactor applications route events based on a Selector
– Like a routing topic, but can be any object
– Regex, URI template, Class.isAssingableFrom, custom logic
@glaforge — @smaldini / #DV13-rtweb
!15
17. Reactor — What does it look like?
Create a reactor context
def
env
=
new
Environment()
!
Build a reactor
parameter
def
reactor
=
Reactors.reactor().env(env).dispatcher(RING_BUFFER).get()
!
reactor.on($('topic')){
Event<String>
ev
-‐>
println
"Hello
$ev.data"
}
React on ‘topic’ events
!
reactor.notify('topic',
Event.wrap('John
Doe'))
Trigger reactor ‘topic’ key
@glaforge — @smaldini / #DV13-rtweb
!17
18. Reactor — Selectors
• Selectors are the left-hand side of an equality comparison
!
– A Selector can be created from any object using $(obj)
(or the long form: Selectors.object(obj))
!
– A Selector can extract data from the matched key
!
– Predicate<T> Selectors can be created to match on domainspecific criteria like header values
@glaforge — @smaldini / #DV13-rtweb
!18
19. Reactor — RegexSelector
• A RegexSelector will match a String by executing the regex
over it
– R(“some.(.*)”)
– Selectors.regex(“some.(.*)”)
@glaforge — @smaldini / #DV13-rtweb
!19
20. Reactor — RegexSelector
!
• A RegexSelector will match a String
by executing the regex over it
!
– R(“some.(.*)”)
!
– Selectors.regex(“some.(.*)”)
@glaforge — @smaldini / #DV13-rtweb
!20
21. Reactor — RegexSelector
Use a Regex Selector and capture group
reactor.on(R('some.(.+)')){
Event<String>
ev
-‐>
def
s
=
ev.headers.get('group1')
}
s will be ‘topic’
!
reactor.notify('some.topic',
Event.wrap('John
Doe'))
Notify a simple String
key to be matched
@glaforge — @smaldini / #DV13-rtweb
!21
22. Reactor — UriSelector
• A UriTemplateSelector will match a String
by extracting bits from a URI
!
– U(“/some/{path}”)
– Selectors.uri(“/some/{path}”)
@glaforge — @smaldini / #DV13-rtweb
!22
23. Reactor — UriSelector
Use a URI Selector and capture fragment
reactor.on(U('/some/**/{topic}')){
Event<String>
ev
-‐>
def
s
=
ev.headers['topic']
}
s will be ‘topic’
!
reactor.notify('/some/to/topic',
Event.wrap('John
Doe'))
Notify a simple String
URI key to be matched
@glaforge — @smaldini / #DV13-rtweb
!23
24. Reactor — Consumer, Function, Supplier, Predicate
public
interface
Consumer<T>
{
void
accept(T
t);
}
Generic Callback
!
public
interface
Supplier<T>
{
T
get();
}
Object Factory
!
public
interface
Function<T,
V>
{
V
apply(T
t);
}
Map Operation
!
public
abstract
class
Predicate<T>
{
boolean
test(T
t);
}
@glaforge — @smaldini / #DV13-rtweb
Filter Operation
!24
25. Reactor — Streams
●
−
−
Streams allow for composition of functions on data
Callback++
Netflix RxJava Observable, JDK 8 Stream
Stream<String>
str
=
obtainStream()
Coerces to Function
!
str.map{
it.toUpperCase()
}
.filter{
someCondition()
}
.consume{
s
-‐>
log.info
"consumed
string
$s"
}
Coerces to Predicate
@glaforge — @smaldini / #DV13-rtweb
Coerces to Consumer
!25
26. Reactor — Promises
●
−
−
Promises supersedes Java Future for composition
Share common functions with Stream
Stateful: only 1 transition allowed
Promise<String>
p
=
doLater()
!
String
s
=
p
.onSuccess
{
s
-‐>
log.info
"consumed
string
$s"
}
.onFailure
{
t
-‐>
log.error
"$t.message"
}
.onComplete
{
log.info
'complete'
}
.await(5,
SECONDS)
!
p.map{
it.toUpperCase()
}.consume{s
-‐>
log.info
"UC:
$s"}
Block for a return value
@glaforge — @smaldini / #DV13-rtweb
!26
27. Reactor — Processor
●
−
−
Thin wrapper around Disruptor RingBuffer
Converts Disruptor API to Reactor API
Uber fast performance for #UberFastData
Processor<Buffer>
proc
!
Operation<Buffer>
op
=
proc.prepare()
op.get().append(data).flip()
op.commit()
!
proc.batch(512)
{
it.append(data).flip()
}
Fill 512 slots and release once
@glaforge — @smaldini / #DV13-rtweb
!27
28. Reactor — Spring
!
Helpers to integrate Reactor into ApplicationContext
●
!
−
@EnableReactor for easy configuration
!
−
Wiring annotated handlers
@glaforge — @smaldini / #DV13-rtweb
!28
30. Reactor — Spring
@Component
class
SimpleHandler
{
Inject reactor
!
@Autowired
Reactor
reactor
!
@Selector('test.topic')
void
onTestTopic(String
s)
{
//
Handle
data
}
}
Register consumer on @reactor
@glaforge — @smaldini / #DV13-rtweb
!30
31. Reactor — Spring
●
−
−
●
●
●
DispatcherTaskExecutor
Not really a high-scale TaskExecutor
Used to get Spring components running in same thread as
Reactor Consumers
ConversionService integration
PromiseHandlerMethodReturnValueHandler (!)
ReactorSubscribableChannel
@glaforge — @smaldini / #DV13-rtweb
!31
32. Reactor — Groovy
●
−
−
−
−
First class citizen language implementation
@CompileStatic ready
Prominent use of Closure as Consumers, Functions and
more
Operator overloading for elegant programming
Full Reactor system Builder
@glaforge — @smaldini / #DV13-rtweb
!32
33. Reactor — Groovy
Works with Groovy 2 CompileStatic
Coerce String to $(string)
@CompileStatic
def
welcome()
{
reactor.on('greetings')
{
String
s
-‐>
reply
"hello
$s"
reply
"how
are
you?"
}
Send data back using
replyTo key header
!
reactor.notify
'greetings',
'Jon'
!
reactor.send('greetings',
'Stephane')
{
println
it
cancel()
}
}
Stop listening for replies
@glaforge — @smaldini / #DV13-rtweb
Coerce data arg to
Event.wrap(data)
Notify & Listen for replies
!33
34. Reactor — Groovy Promises and Streams
Build an async function
def
promise
=
Promises.task
{
longStuff();
1
}
get()
!
def
transformation
=
promise
|
{
it
+
1
}
transformation.await()
==
2
Pipe promise with the
!
def
deferredStream
=
Streams.defer().get()
closure transformation
(deferredStream
&
{
it
>
2
})
<<
{
send(it)
}
!
deferredStream
<<
1
<<
2
<<
3
<<
4
Filter the stream with
the right hand closure
predicate
@glaforge — @smaldini / #DV13-rtweb
Add callback after filter
Send data
!34
35. Reactor — Groovy Environment
Works with Groovy 2
@CompileStatic
Prepare an environment
builder
GroovyEnvironment.create
{
environment
{
defaultDispatcher
=
"test"
!
which dispatcher to use
when creating a reactor
dispatcher('test')
{
type
=
DispatcherType.SYNCHRONOUS
}
}
Build a standard
}.environment()
Return a ready to
use Environment
@glaforge — @smaldini / #DV13-rtweb
Dispatcher
!35
36. Reactor — Groovy Environment
Build a named Reactor
GroovyEnvironment.create
{
reactor('test1')
{
Intercept the data
stream('test')
{
consume
{
ev-‐>
stream coming by the
log.info
ev.data
selector $(‘test’)
}
}
on('test')
{
Stream builder
reply
it
}
}
}
Attach inline consumers
@glaforge — @smaldini / #DV13-rtweb
!36
37. Reactor — Extensive Awesomeness
●
TCP Client/Server, with a Netty 4 implementation
●
Buffer tools
●
Sequencer support, for event ordering
●
Work Queue support with OoB Java Chronicle implementation
●
Log Appender
@glaforge — @smaldini / #DV13-rtweb
!37
38. Reactor — Roadmap
1.1 discussions
●
−
StateBox: a safe tool for concurrent writes
−
Better Timer management
−
Spring XD, Spring 4
−
Exploring Distributed Reactors
●
Voice your interest and your use-case here
@glaforge — @smaldini / #DV13-rtweb
!38
39. Reactor — Roadmap
1.1 discussions
●
−
HTTP helpers
−
Improved RingBuffer API for multithreaded consumers
(slow consumers)
−
More Groovy Love: Buffer, TCP, Processor, Time,
@glaforge — @smaldini / #DV13-rtweb
!39
40. Reactor — Uber Community Contribs
●
−
Meltdown: A Clojure binding by @michaelklishin &
@ifesdjeen
https://github.com/clojurewerkz/meltdown
@glaforge — @smaldini / #DV13-rtweb
!40
41. Reactor — Uber Community Contribs
!
●
−
High Performance Couchbase ingestion by @daschl
http://nitschinger.at/Using-the-Reactor-Processor-for-HighPerformance-TCP
!
●
Benefits of using Reactor Processor, TCP and Batching
facilities
@glaforge — @smaldini / #DV13-rtweb
!41
44. Grails — The Age of Asynchronous
Fact #1:
– HTTP request thread is critical path
– Do the barely necessary for fast rendering
– If it’s long*, do it in a separate thread
@glaforge — @smaldini / #DV13-rtweb
!44
45. Grails — The Age of Asynchronous
Fact #2:
– Creating new Threads needs caution
– Context switching hurts performances
– Concurrent programming is tricky*
@glaforge — @smaldini / #DV13-rtweb
!45
46. Grails — The Age of Asynchronous
Fact #3:
– Burden on your application is never constant
– Scaling Up is a good start…
– …And Scaling Out is only next
@glaforge — @smaldini / #DV13-rtweb
!46
47. Grails — The Age of Asynchronous
So I have to use background threads ?
But using them might lead to issues and headaches ?
And what if I really need to scale out ?
@glaforge — @smaldini / #DV13-rtweb
!47
48. Grails — Reactive Programming Recap
• Adding a level of indirection :
Driving your application with Events
• Laziness is key
• Scale up/out by tweaking dispatching
@glaforge — @smaldini / #DV13-rtweb
!48
49. Grails — The Big Picture
Application
Service
Consumer
Service
Consumer
Publish/Subscribe
Events
Bus
Service
Consumer
@glaforge — @smaldini / #DV13-rtweb
Service
Consumer
Service
Consumer
!49
50. Grails — The Big Picture
Cloud
App
Publish/Subscribe
App
Events
Bus
App
App
App
@glaforge — @smaldini / #DV13-rtweb
!50
52. Grails — Origins : Platform-Core plugin
• An initiative to provide modern tools for grails development
!
• Among them: the Events API
• An abstraction used in a few Grails applications today to
decouple logic from producers
!
• grails-events can be considered as
Platform Core Events API 2.0
@glaforge — @smaldini / #DV13-rtweb
!52
53. Grails — Why a new plugin ?
• New features. And quite a few.
– Streaming data, Selectors, Queue
!
• Based on a new solid foundation – Reactor
– Where Platform-core Events best ideas have leaked
!
• Semantic changes
– But relatively straightforward migration path
@glaforge — @smaldini / #DV13-rtweb
!53
54. Grails — Why a new plugin ?
• Lightweight, only focused on events
!
• Ready to be embedded in a future Grails version
• Complete the asynchronous story
• Could enable runtime plugin deployment
@glaforge — @smaldini / #DV13-rtweb
!54
55. Grails — So what Grails Events is about
• Grails Apps and Plugins can use Events to:
– Listen for plugins/app events
– Start simple with in-memory eventing (#uberfastdata)
– Do Asynchronous calls (default)
– Increase in flexibility if required
@glaforge — @smaldini / #DV13-rtweb
!55
57. Grails — Semantics: Consumer
• A Consumer:
– Accepts an Event
– Is registered in a Service or Events artifact, or by calling on()
– Can be thread safe
• Depending on the dispatcher type
• Assuming the consumer is not registered more than once
@glaforge — @smaldini / #DV13-rtweb
!57
58. Grails — Semantics: Selector
• A Selector:
– Matches an event key
– Is paired with a consumer during its registration
– Any bean method can be transformed into consumer
with @Selector
@glaforge — @smaldini / #DV13-rtweb
!58
59. Grails — Semantics: Reactor
• A Reactor:
– Is a dedicated Consumer Registry
– Has an assigned Dispatcher
– Uses a specific Event Router
!
• Usually, if the Dispatcher doesn’t need to be adapted, reuse the
default reactor grailsReactor
@glaforge — @smaldini / #DV13-rtweb
!59
60. Grails — Pattern Examples : Event Driven CQRS
http://martinfowler.com/bliki/CQRS.html
Save a GORM entity
SaveService
GORM
DB
PostProcessingService
Insert Record
@glaforge — @smaldini / #DV13-rtweb
Trigger afterInsert
event
Consume afterInsert events
!60
73. Grails — GORM events
• GORM is now an extension
– Using ext(‘gorm’, true) on any candidate reactor
– Applicable Selectors: simple topic form (beforeInsert...)
– A boolean reply is evaluated as a cancel directive
reactor('someGormReactor'){
dispatcher
=
new
SynchronousDispatcher()
ext
'gorm',
true
@Selector(reactor
=
'someGormReactor')
}
@ReplyTo
boolean
beforeValidate(Book
b){
false
}
@glaforge — @smaldini / #DV13-rtweb
!73
82. Grails — Generating Simple Browsers bridges
includes
=
'push'
!
Conventional name to
override ‘browser’ reactor
doWithReactor
=
{
reactor('browser')
{
ext
'browser',
[
'control',
'move',
'fire',
'leave'
]
}
reactor(‘grailsReactor')
{
ext
'browser',
['sleepBrowser']
Bridge browser to these reactor
consumers $(‘control),…
!
stream(‘sleepBrowser')
{
filter
{
it.data
==
'no'
}
}
}
}
@glaforge — @smaldini / #DV13-rtweb
Bridge browser to this reactor
consumer $(‘sleepBrowser)
Prevent data ‘no’ to be
dispatched to browser bridges
!82
83. Grails — React on server side events
Inject grailsEvents.js (requires resources plugin)
Create a connection
between the browser and
the current Grails app
Listen for $(‘afterInsert’) events
@glaforge — @smaldini / #DV13-rtweb
!83
84. Grails — Generating Advanced Browsers bridges
includes
=
['push']
!
Include PushEvents (configure a
reactor for events from Browsers)
doWithReactor
=
{
reactor(‘grailsReactor')
{
ext
'gorm',
true
ext
'browser',
[
'test':
true,
'afterInsert':
[
browserFilter:
{m,
r
-‐>
true
}
],
(R("sampleBro-‐.*"))
:
true,
]
}
reactor(EventsPushConstants.FROM_BROWSERS)
{
ext
'browser',
[R("sampleBro-‐.*")]
}
}
Listen on GORM events
Extension to bridge
Browsers consumers to
Server-side pair
Events are only routed, from
Browsers to bridged Browsers
@glaforge — @smaldini / #DV13-rtweb
Override “From Browsers” reactor
and bridge consumers
!84
85. Grails — The Bad Stuff
• events-si : Events API on top of Spring Integration
– Not here (just) yet
!
• events-vertx : Abandoned experiment
– Working around Distributed Reactor
!
• Stream DSL could be optimized
– Reducing the number of objects
@glaforge — @smaldini / #DV13-rtweb
!85
86. Grails — Roadmap
• events:
– Document, especially for Migration from Platform Core
– Stick with latest awesome features from Reactor
• Still Many API to expose: Processors, Buffer, TCP, Queues,
Sequencer…
!
• events-push -> events-atmosphere :
– Add support for replyTo
– extract to standalone module : reactor-atmosphere
@glaforge — @smaldini / #DV13-rtweb
!86
87. Grails — Roadmap
• events-sockjs:
– Involves Reactor work here
!
• events-si:
– Supports new events plugin
!
• events-xx:
– The plugin where you are the hero
@glaforge — @smaldini / #DV13-rtweb
!87
90. Groovy, Reactor, Grails and the realtime web
• Embrace modern reactive architectures with Groovy,
Reactor and Grails!
• Groovy is a versatile language, that enables development of
concise and functional oriented applications
• Reactor fuels your asynchronous and reactive applications
with its ultra fast dispatching engine and non-blocking model.
• Grails supports your today's and tomorrow's web app design,
tooled with the right plugins you are prepared for responsive
and interactive applications
@glaforge — @smaldini / #DV13-rtweb
!90