Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.
Groovy, Reactor, Grails 

& the realtime web
Guillaume Laforge 

@glaforge !

Stéphane Maldini

@smaldini !
Stéphane
Maldini
Consultant and Reactor committer
at
.
!

@smaldini
1
t
r
a
P

Reactor
Reactor — Housekeeping
!

• Tweet questions during the presentation	

– @ProjectReactor
!

• Stop us anywhere if you have ...
Reactor — Reactive Architecture ?
REACTIVE
AGILE
EVENT DRIVEN
SCALABLE
AVAILABLE

@glaforge — @smaldini / #DV13-rtweb

!5
Reactor — Reactive Architecture ?
• A good description is available on: 

http://www.reactivemanifesto.org/	

!

• Functio...
Reactor — Threading model matters
• Context switching hurts performances	

• Locking hurts performances	

• Message passin...
Reactor — Dealing with performances
• Actors solve the locking and context switching issues 

by becoming state boxes	

• ...
Reactor — LMAX Disruptor and Ring Buffer
• LMAX Disruptor deals with message passing issues	

• Based on a Ring Buffer str...
Reactor — Disruptor performances

@glaforge — @smaldini / #DV13-rtweb

!10
Reactor — Trisha’s pretty picture of Disruptor
http://mechanitis.blogspot.co.uk/2011/07/dissectingdisruptor-writing-to-rin...
Reactor — In love with Disruptor
• Reactor best performances are derived from LMAX Disruptor	

!

• LMAX Disruptor can be ...
Reactor — A foundation part of Spring IO

@glaforge — @smaldini / #DV13-rtweb

!13
Reactor — What is it?
!

• Reactor is a distillation of other libraries and best-practices	

– Elements of other patterns ...
Reactor — What can I build with it?
• Reactor applications are reactive	

– Reactive Extensions in .NET	

– Netflix RxJava	...
Reactor — Landscape

@glaforge — @smaldini / #DV13-rtweb

!16
Reactor — What does it look like?
Create a reactor context
def	
  env	
  =	
  new	
  Environment()	
  
!

Build a reactor
...
Reactor — Selectors
• Selectors are the left-hand side of an equality comparison	

!

– A Selector can be created from any...
Reactor — RegexSelector
• A RegexSelector will match a String by executing the regex
over it	

– R(“some.(.*)”)
– Selector...
Reactor — RegexSelector
!

• A RegexSelector will match a String 

by executing the regex over it	

!

– R(“some.(.*)”)
!
...
Reactor — RegexSelector
Use a Regex Selector and capture group
reactor.on(R('some.(.+)')){	
  Event<String>	
  ev	
  -­‐>	...
Reactor — UriSelector
• A UriTemplateSelector will match a String 

by extracting bits from a URI
!

– U(“/some/{path}”)
–...
Reactor — UriSelector
Use a URI Selector and capture fragment
reactor.on(U('/some/**/{topic}')){	
  Event<String>	
  ev	
 ...
Reactor — Consumer, Function, Supplier, Predicate
public	
  interface	
  Consumer<T>	
  {	
  
	
  	
  	
  	
  	
  	
  	
  ...
Reactor — Streams
●

−
−

Streams allow for composition of functions on data	

Callback++	

Netflix RxJava Observable, JDK ...
Reactor — Promises
●

−
−

Promises supersedes Java Future for composition	

Share common functions with Stream
Stateful: ...
Reactor — Processor
●

−
−

Thin wrapper around Disruptor RingBuffer
Converts Disruptor API to Reactor API	

Uber fast per...
Reactor — Spring
!

Helpers to integrate Reactor into ApplicationContext	


●

!

−

@EnableReactor for easy configuration	...
Reactor — Spring
Setup Environment

@Configuration	
  
@EnableReactor	
  
class	
  ReactorConfiguration	
  {	
  
!

	
  	
...
Reactor — Spring
@Component	
  
class	
  SimpleHandler	
  {	
  

Inject reactor

!

	
  	
  @Autowired	
  Reactor	
  react...
Reactor — Spring
●

−
−
●
●

●

DispatcherTaskExecutor 	

Not really a high-scale TaskExecutor	

Used to get Spring compon...
Reactor — Groovy
●

−
−
−
−

First class citizen language implementation	

@CompileStatic ready	

Prominent use of Closure...
Reactor — Groovy
Works with Groovy 2 CompileStatic

Coerce String to $(string)

@CompileStatic	
  
def	
  welcome()	
  {	
...
Reactor — Groovy Promises and Streams
Build an async function

def	
  promise	
  =	
  Promises.task	
  {	
  longStuff();	
...
Reactor — Groovy Environment
Works with Groovy 2
@CompileStatic

Prepare an environment
builder

GroovyEnvironment.create	...
Reactor — Groovy Environment
Build a named Reactor

GroovyEnvironment.create	
  {	
  
	
  	
  	
  	
  	
  	
  	
  	
  reac...
Reactor — Extensive Awesomeness
●

TCP Client/Server, with a Netty 4 implementation	


●

Buffer tools	


●

Sequencer sup...
Reactor — Roadmap
1.1 discussions

●

−

StateBox: a safe tool for concurrent writes	


−

Better Timer management	


−

S...
Reactor — Roadmap
1.1 discussions

●

−

HTTP helpers

−

Improved RingBuffer API for multithreaded consumers
(slow consum...
Reactor — Uber Community Contribs
●

−

Meltdown: A Clojure binding by @michaelklishin &
@ifesdjeen 	

https://github.com/...
Reactor — Uber Community Contribs
!

●

−

High Performance Couchbase ingestion by @daschl	

http://nitschinger.at/Using-t...
Demo
2
t
r
a
P

Grails
Grails — The Age of Asynchronous
Fact #1:	

– HTTP request thread is critical path	

– Do the barely necessary for fast re...
Grails — The Age of Asynchronous
Fact #2:	

– Creating new Threads needs caution	

– Context switching hurts performances	...
Grails — The Age of Asynchronous

Fact #3:	

– Burden on your application is never constant	

– Scaling Up is a good start...
Grails — The Age of Asynchronous

So I have to use background threads ?	

But using them might lead to issues and headache...
Grails — Reactive Programming Recap
• Adding a level of indirection : 

Driving your application with Events
• Laziness is...
Grails — The Big Picture
Application
Service
Consumer
Service
Consumer

Publish/Subscribe
Events
Bus

Service
Consumer

@g...
Grails — The Big Picture
Cloud
App
Publish/Subscribe

App
Events
Bus

App

App
App

@glaforge — @smaldini / #DV13-rtweb

!...
Introducing	
  GRAILS-­‐EVENTS	
  plugin
BOOM!

worse slide ever™
@glaforge — @smaldini / #DV13-rtweb

!51
Grails — Origins : Platform-Core plugin
• An initiative to provide modern tools for grails development	

!

• Among them: ...
Grails — Why a new plugin ?
• New features. And quite a few.	

– Streaming data, Selectors, Queue	

!

• Based on a new so...
Grails — Why a new plugin ?
• Lightweight, only focused on events	

!

• Ready to be embedded in a future Grails version	
...
Grails — So what Grails Events is about
• Grails Apps and Plugins can use Events to:	

– Listen for plugins/app events	

–...
Grails — Installing Grails Events
• It’s a binary plugin (!)	

• Requires Grails 2.2+
repositories	
  {	
  
	
  	
  	
  	
...
Grails — Semantics: Consumer
• A Consumer:	

– Accepts an Event	

– Is registered in a Service or Events artifact, or by c...
Grails — Semantics: Selector
• A Selector:	

– Matches an event key	

– Is paired with a consumer during its registration
...
Grails — Semantics: Reactor
• A Reactor:	

– Is a dedicated Consumer Registry	

– Has an assigned Dispatcher	

– Uses a sp...
Grails — Pattern Examples : Event Driven CQRS
http://martinfowler.com/bliki/CQRS.html

Save a GORM entity
SaveService
GORM...
Grails — Pattern Examples : Modular Architecture
Core application untouched

Trigger ‘request’ event

Main Application

Re...
Grails — Pattern Examples : Background Processing
Return immediately
Grails Controller

REST service

Request Service

HTT...
Grails — Sending Events (grails-platform-core)
def	
  user	
  =	
  new	
  User(params).save()	
  
!

event('mailRegistrati...
Grails — Sending Events (grails-events)
def	
  user	
  =	
  new	
  User(params).save()	
  
!

event('mailRegistration',	
 ...
Grails — Consuming Events (grails-platform-core)
class	
  UserService{	
  
	
  	
  	
  	
  @grails.events.Listener	
  
	
 ...
Grails — Consuming Events (grails-events)
Consume on
Selector(method name)

class	
  UserService{	
  
	
  	
  
	
  	
  	
 ...
Grails — A new Artifact conf/XxxxEvents
includes	
  =	
  ['default']	
  

Merge with DefaultsEvents

!

doWithReactor	
  =...
Grails — Reactor awesomeness : Selectors
• Listen for arbitrary keys	

• import static reactor.event.selector.Selectors.*
...
Grails — Reactor awesomeness : Stream API
• Reactive Extensions programming style	

• Avoid callback hell
Build a Stream t...
Grails — Reactor awesomeness: Promise API
• Grails 2.3 Promises become a Reactor Promises	

• Benefits from Dispatcher over...
Grails — Reactor awesomeness : Routing
• During event dispatching, consumers list is selected	

• Publish Subscribe is the...
Grails — Extensibility
!

• Main extension points:	

– Dispatcher, Selector, Registry, EventRouter, Consumer
!

• Metadata...
Grails — GORM events
• GORM is now an extension	

– Using ext(‘gorm’, true) on any candidate reactor	

– Applicable Select...
GRAILS-­‐EVENTS-­‐PUSH	
  plugin
Eventing over HTTP!

@glaforge — @smaldini / #DV13-rtweb

!74
Grails — Pattern Examples : “Realtime” web
Push reply to browser: Websocket, SSE, long-polling…

Reply a new event

Respon...
Grails — An elegant solution to browser push
• Powered by Atmosphere 2	

• Automatically picks an adapted protocol:	

– We...
Grails — Installing Grails Events Push
1. Install Grails Events plugin	

2. Install Grails Events Push plugin
grails.servl...
Grails — grails-events-push Lifecycle 1 - Handshake

Browser

EventsPushHandler

Adapt Protocol and Open
new persistent co...
Grails — grails-events-push Lifecycle 2 - Register
Consumer registered on all Reactor with
‘browser’ extension enabled
Bro...
Grails — grails-events-push Lifecycle 3 - Notify
RequestService consumes on matching
Selector within the ‘browser’ Reactor...
Grails — grails-events-push Lifecycle 4 - Consume
Notify ‘browser’ enabled
Reactor and match key
Browser

Reactor(s)

Resp...
Grails — Generating Simple Browsers bridges
includes	
  =	
  'push'	
  
!

Conventional name to
override ‘browser’ reactor...
Grails — React on server side events
Inject grailsEvents.js (requires resources plugin)
Create a connection
between the br...
Grails — Generating Advanced Browsers bridges
includes	
  =	
  ['push']	
  
!

Include PushEvents (configure a
reactor for...
Grails — The Bad Stuff
• events-si : Events API on top of Spring Integration	

– Not here (just) yet	

!

• events-vertx :...
Grails — Roadmap
• events: 	

– Document, especially for Migration from Platform Core	

– Stick with latest awesome featur...
Grails — Roadmap
• events-sockjs:	

– Involves Reactor work here 	

!

• events-si: 	

– Supports new events plugin	

!

•...
Demo
4
t
r
a
P

Summary
Groovy, Reactor, Grails and the realtime web
• Embrace modern reactive architectures with Groovy,
Reactor and Grails!	

• ...
Prochain SlideShare
Chargement dans…5
×

Reactor grails realtime web devoxx 2013

3 850 vues

Publié le

Publié dans : Technologie
  • Soyez le premier à commenter

Reactor grails realtime web devoxx 2013

  1. 1. Groovy, Reactor, Grails 
 & the realtime web Guillaume Laforge 
 @glaforge ! Stéphane Maldini
 @smaldini !
  2. 2. Stéphane Maldini Consultant and Reactor committer at . ! @smaldini
  3. 3. 1 t r a P Reactor
  4. 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
  5. 5. Reactor — Reactive Architecture ? REACTIVE AGILE EVENT DRIVEN SCALABLE AVAILABLE @glaforge — @smaldini / #DV13-rtweb !5
  6. 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
  7. 7. Reactor — Threading model matters • Context switching hurts performances • Locking hurts performances • Message passing hurts performances • Blocking for a thread hurts performances • Creating Threads needs memory @glaforge — @smaldini / #DV13-rtweb !7
  8. 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. 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
  10. 10. Reactor — Disruptor performances @glaforge — @smaldini / #DV13-rtweb !10
  11. 11. Reactor — Trisha’s pretty picture of Disruptor http://mechanitis.blogspot.co.uk/2011/07/dissectingdisruptor-writing-to-ring.html @glaforge — @smaldini / #DV13-rtweb !11
  12. 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. 13. Reactor — A foundation part of Spring IO @glaforge — @smaldini / #DV13-rtweb !13
  14. 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. 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
  16. 16. Reactor — Landscape @glaforge — @smaldini / #DV13-rtweb !16
  17. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 28. Reactor — Spring ! Helpers to integrate Reactor into ApplicationContext ● ! − @EnableReactor for easy configuration ! − Wiring annotated handlers @glaforge — @smaldini / #DV13-rtweb !28
  29. 29. Reactor — Spring Setup Environment @Configuration   @EnableReactor   class  ReactorConfiguration  {   !                @Bean  Reactor  input(Environment  env)  {                                  Reactors.reactor().env(env)                                                  .dispatcher(RING_BUFFER).get()                  }                 !                @Bean  Reactor  output(Environment  env)  {                                  Reactors.reactor().env(env)                                                  .dispatcher(RING_BUFFER).get()                  }                 } @glaforge — @smaldini / #DV13-rtweb !29
  30. 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. 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. 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. 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. 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. 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. 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. 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. 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. 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. 40. Reactor — Uber Community Contribs ● − Meltdown: A Clojure binding by @michaelklishin & @ifesdjeen https://github.com/clojurewerkz/meltdown @glaforge — @smaldini / #DV13-rtweb !40
  41. 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
  42. 42. Demo
  43. 43. 2 t r a P Grails
  44. 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. 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. 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. 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. 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. 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. 50. Grails — The Big Picture Cloud App Publish/Subscribe App Events Bus App App App @glaforge — @smaldini / #DV13-rtweb !50
  51. 51. Introducing  GRAILS-­‐EVENTS  plugin BOOM! worse slide ever™ @glaforge — @smaldini / #DV13-rtweb !51
  52. 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. 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. 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. 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
  56. 56. Grails — Installing Grails Events • It’s a binary plugin (!) • Requires Grails 2.2+ repositories  {          //...                mavenRepo  "http://repo.springsource.org/libs-­‐snapshot"          mavenRepo  "http://repo.grails.org/grails/libs-­‐snapshots-­‐local/"   }   ! dependencies  {          compile  'org.grails.plugins:events:1.0.0.BUILD-­‐SNAPSHOT'   }   @glaforge — @smaldini / #DV13-rtweb !56
  57. 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. 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. 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. 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
  61. 61. Grails — Pattern Examples : Modular Architecture Core application untouched Trigger ‘request’ event Main Application RequestService Notification Plugin NotificationService Create a decoupled module @glaforge — @smaldini / #DV13-rtweb Consume ‘request’ events !61
  62. 62. Grails — Pattern Examples : Background Processing Return immediately Grails Controller REST service Request Service HTTP Request Trigger ‘request’ event (async) Long REST call @glaforge — @smaldini / #DV13-rtweb !62
  63. 63. Grails — Sending Events (grails-platform-core) def  user  =  new  User(params).save()   ! event('mailRegistration',  user)       //event('mailRegistration',  user).waitFor()       //event  topic:'mailRegistration',  data:user       //event  topic:'mailRegistration',  data:user,  fork:false       render(view:'sendingRegistrationMail') @glaforge — @smaldini / #DV13-rtweb !63
  64. 64. Grails — Sending Events (grails-events) def  user  =  new  User(params).save()   ! event('mailRegistration',  user)                 event('mailRegistration',  user)  {          if(it  ==  ‘end')  {                  cancel()          }   }       Non blocking call to trigger app consumers Do things on each reply Map notation ! //  event  key:  'mailRegistration',  data:  user   ! render(view:  'sendingRegistrationMail') @glaforge — @smaldini / #DV13-rtweb !64
  65. 65. Grails — Consuming Events (grails-platform-core) class  UserService{          @grails.events.Listener          def  mailRegistration(User  user)  {                  sendMail  {                          to  user.mail                          subject  "Confirmation"                          html  g.render(template:"userMailConfirmation")                  }          }   !        @grails.events.Listener(topic=  "mailRegistration")          def  mailRegistration2(org.grails.plugin.platform.events.EventMessage  msg)  {                  sendMail{                        to  msg.data.mail                        subject  "Confirmation"                        html  g.render(template:  "userMailConfirmation")                  }          }   } @glaforge — @smaldini / #DV13-rtweb !65
  66. 66. Grails — Consuming Events (grails-events) Consume on Selector(method name) class  UserService{              @reactor.spring.annotation.Selector          def  mailRegistration(User  user){                  sendMail{                          to  user.mail                          subject  "Confirmation"                          html  g.render(template:  "userMailConfirmation")                  }          }   Consume on this specific topic !        @reactor.spring.annotation.Selector("mailRegistration")          def  mailRegistration2(reactor.event.Event  msg){                  sendMail{                          to  msg.data.mail                          subject  "Confirmation"                          html  g.render(template:"userMailConfirmation")                  }          }   } @glaforge — @smaldini / #DV13-rtweb Event typed signature to inspect enveloppe (‘headers…) !66
  67. 67. Grails — A new Artifact conf/XxxxEvents includes  =  ['default']   Merge with DefaultsEvents ! doWithReactor  =  {          reactor(EventsApi.GRAILS_REACTOR)  {                  on('someTopic')  {                          reply  'test'                                          }                                                                                                        }                                                                                                                                        reactor(‘someGormReactor')  {                                                                                                            dispatcher  =  new  SynchronousDispatcher()                  ext  'gorm',  true                                                                                                                   Build a GroovyEnvironment Reactor Groovy Builders ! Grails extension: accept GORM events                stream  {                          consume  {                                  log.info  "Some  gorm  event  is  flowing  with  data  $it.data"                          }.when(Throwable)  {                                  log.error  "Ow  snap!",  it                          }                                                                                                                                                        }                                                      }                                                                                                                                                         } @glaforge — @smaldini / #DV13-rtweb !67
  68. 68. Grails — Reactor awesomeness : Selectors • Listen for arbitrary keys • import static reactor.event.selector.Selectors.* on(T(SpecificClassType))  {   Listen for SpecificClassType                reply  it                                   }                                                                                                 ! Send using right key type event(new  SpecificClassType(),  'data')                                                           ! ! Listen for an URI on(uri(‘/some/{captureIt}'))  {                                                                                          reply  it.headers.captureIt   }                                                                                                                                     ! Send using matching URI event('/some/hourray',  'data')         @glaforge — @smaldini / #DV13-rtweb !68
  69. 69. Grails — Reactor awesomeness : Stream API • Reactive Extensions programming style • Avoid callback hell Build a Stream to capture any reply $(‘test’) consumers may reply withStream  {          event(key:  'test',  data:  1)   }.when(Exception,  {   If a consumer fails        log.info  "exception:$it"   }).map  {   Transform result        callExternalService(it)   }.consume('clientKey',  reactor('browser')) Reroute to key ‘clientKey’ on Reactor ‘browser’ @glaforge — @smaldini / #DV13-rtweb !69
  70. 70. Grails — Reactor awesomeness: Promise API • Grails 2.3 Promises become a Reactor Promises • Benefits from Dispatcher overriding • Powerful once Combined with Consumers dispatcher(ReactorPromise.PromiseDispatcher)  {          type  =  DispatcherType.RingBuffer          backlog  =  512   } task  {          def  res  =   longProcessing()          render  res   } @glaforge — @smaldini / #DV13-rtweb !70
  71. 71. Grails — Reactor awesomeness : Routing • During event dispatching, consumers list is selected • Publish Subscribe is the default • Possible to assign different routing strategy reactor('test1')  {          routingStrategy  'round-­‐robin'          on('test')  {                  reply  '1'   Will reply 1, 2, 1, 2, 1, 2…        }                        on('test')  {                  reply  '2'          }                 } @glaforge — @smaldini / #DV13-rtweb !71
  72. 72. Grails — Extensibility ! • Main extension points: – Dispatcher, Selector, Registry, EventRouter, Consumer ! • Metadata in Reactor Events DSL: – ext(‘someExtension’, [ ‘doStuff’: true ]) @glaforge — @smaldini / #DV13-rtweb !72
  73. 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
  74. 74. GRAILS-­‐EVENTS-­‐PUSH  plugin Eventing over HTTP! @glaforge — @smaldini / #DV13-rtweb !74
  75. 75. Grails — Pattern Examples : “Realtime” web Push reply to browser: Websocket, SSE, long-polling… Reply a new event ResponseService Browser Return immediately @glaforge — @smaldini / #DV13-rtweb Grails Controller RequestService Trigger async event !75
  76. 76. Grails — An elegant solution to browser push • Powered by Atmosphere 2 • Automatically picks an adapted protocol: – WebSockets, ServerSideEvent, Streaming, Polling… • Consumer bridges for server-to-client push • Reactor bridge for client-to-server push • Javascript library @glaforge — @smaldini / #DV13-rtweb !76
  77. 77. Grails — Installing Grails Events Push 1. Install Grails Events plugin 2. Install Grails Events Push plugin grails.servlet.version  =  "3.0"   grails.tomcat.nio  =  true   ! Use a “long-connection” friendly tomcat configuration grails.project.dependency.resolution  =  {          repositories  {          //...                  mavenRepo  "https://oss.sonatype.org/content/repositories/snapshots"          }                                            dependencies  {                                  //...                                                    compile  'org.grails.plugins:events:1.0.0.BUILD-­‐SNAPSHOT'          }                                                                                            plugins  {                                                                                            //...                                                                                                    runtime  ":jquery:1.10.2"                                                                                                                                  runtime  ":events-­‐push:1.0.0.BUILD-­‐SNAPSHOT"                                                }   } @glaforge — @smaldini / #DV13-rtweb !77
  78. 78. Grails — grails-events-push Lifecycle 1 - Handshake Browser EventsPushHandler Adapt Protocol and Open new persistent connection @glaforge — @smaldini / #DV13-rtweb !78
  79. 79. Grails — grails-events-push Lifecycle 2 - Register Consumer registered on all Reactor with ‘browser’ extension enabled Browser Reactor(s) Bridge a Client Consumer with a remote Reactor Consumer @glaforge — @smaldini / #DV13-rtweb !79
  80. 80. Grails — grails-events-push Lifecycle 3 - Notify RequestService consumes on matching Selector within the ‘browser’ Reactor Browser ‘browser’ Reactor RequestService Notify any key @glaforge — @smaldini / #DV13-rtweb !80
  81. 81. Grails — grails-events-push Lifecycle 4 - Consume Notify ‘browser’ enabled Reactor and match key Browser Reactor(s) ResponseService Push event (WS, SSE…) @glaforge — @smaldini / #DV13-rtweb !81
  82. 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. 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. 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. 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. 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. 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
  88. 88. Demo
  89. 89. 4 t r a P Summary
  90. 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

×