This document discusses using asynchronous programming and reactive programming with events to build highly scalable applications. It introduces the Grails Events plugin, which provides an eventing framework based on the Reactor library. The Grails Events plugin allows applications and plugins to listen for and publish events to support asynchronous processing. It also provides stream processing capabilities and integration with technologies like GORM and Atmosphere for browser push notifications.
3. Solving a basic problem
“Your valuable users don’t like waiting”
4. 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
5. The Age of Asynchronous
Fact #2:
– Creating new Threads needs caution
– Context switching hurts performances
– Concurrent programming is tricky*
6. 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
7. Dilemma
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 ?
8. Reactive programming
• Adding a level of indirection :
Driving your application with Events
• Laziness is key
• Scale up/out by tweaking dispatching
9. The big picture
Events
Bus
Point to point
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Service
Consumer
Application
14. The new deal
• New features. And quite a few.
– Streaming data, Selectors, Queue
• Based on a solid foundation – Reactor
– Where Platform-core Events best ideas have leaked
• Semantic changes
– But relatively easy migration path
15. 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
– Do Asynchronous calls (default)
– Increase in flexibility if required
18. 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
19. Semantics: Selector
• A Selector:
– Matches an event key
– Is paired with a consumer during its registration
20. 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
21. Platform Core: Sending Events
def user = new User(params).save()
//non-blocking call, will trigger application listeners for this topic
event('mailRegistration', user)
//blocking call :
//event('mailRegistration', user).waitFor()
//can also be written like that
//event topic:'mailRegistration', data:user
//and if you need to reuse the current thread
//event topic:'mailRegistration', data:user, fork:false
render(view:'sendingRegistrationMail’)
22. Events: Sending Events
def user = new User(params).save()
//non-blocking call, will trigger application listeners for this topic
event('mailRegistration', user)
//Do things on each reply :
//event('mailRegistration', user){
if(it == ‘end’){
cancel()
}
}
//can also be written like that
//event key:'mailRegistration', data:user
render(view:'sendingRegistrationMail')
23. Platform Core Events : Consuming Events
class UserService{
//use method name 'mailRegistration' as topic name
//can also use custom topic name using topic arg: @Listener(topic='test')
@grails.events.Listener
def mailRegistration(User user){
sendMail{
to user.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
//Can also receive an EventMessage to get more information on this particular event)
@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")
}
}
}
24. Events : Consuming Events
class UserService{
//use method name 'mailRegistration' as topic name
//can also use custom topic name using topic arg: @Selector(‘test')
@reactor.spring.annotation.Selector
def mailRegistration(User user){
sendMail{
to user.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
//Can also receive an Event to get more information on this particular event)
@reactor.spring.annotation.Selector("mailRegistration")
def mailRegistration2(reactor.event.Event msg){
sendMail{
to msg.data.mail
subject "Confirmation"
html g.render(template:"userMailConfirmation")
}
}
}
28. Reactor awesomeness : Promise API
• Grails 2.3 Promises become a Reactor Promises
• Benefits from Dispatcher overriding
• Powerful once Combined with Consumers
29. Reactor awesomeness : Routing
• During event dispatching, consumers list is selected
• Publish Subscribe is the default
• Possible to assign different routing strategy
31. 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
40. 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
41. 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 :
– More robust subscription mech
– Update atmosphere client
– Add support for replyTo
– Add support for binary
42. Roadmap
• events-sockjs:
– Involves Reactor work here
• events-si:
– Supports new events plugin
• events-xx:
– The plugin where you are the hero
43. Learn More. Stay Connected.
• Follow-up
– Reactor repository: http://github.com/reactor/
– Mail: @smaldini / smaldini@gopivotal.com
• Talk to us on Twitter: @springcentral
• Find Session replays on YouTube: spring.io/video
Editor's Notes
#5: Challenge long* Long is sometimes ok or a necessary evil.