SlideShare a Scribd company logo
1 of 50
Download to read offline
© 2017 Autodesk
John Scattergood
Senior Principal Engineer
JavaOne 2017
Reactive Microservices
with JRuby and Docker
§ Engineer at Autodesk
§ Enjoy coding in Java, Ruby,
Groovy and JavaScript
§ Run JRuby apps in production
that serve millions of requests/day
§ First time JavaOne Speaker
@johnscattergood
About Me
Reactive Systems
Our System
Market Updates
Stock Updates
Alerts/Rules
Notifications
SMS
DB Autoscaler
Cluster
Scale
§ Price Alerts (eCommerce)
§ APM and Infrastructure Monitoring (IT)
§ Fraud Detection (Credit)
§ Devices, Transponders, etc. (IOT)
Other Domains
Tools
§ Dynamic
§ Object-oriented w/ first class functions
§ Expressive
§ Flexible
§ Easy to learn
Ruby
Ruby is simple in appearance, but is very complex inside just like our human body
- Yukihiro “Matz” Matsumoto
Ruby Creator
@memo = { 1 => 1, 2 => 2 }
def fib(n)
@memo[n] ||= fib(n - 1) + fib(n - 2)
end
fib(100)
=> 573147844013817084101
Fibonnaci
§ Fully compatible implementation of Ruby
§ Includes benefits of JVM
§ High Performance
§ True multi-threading
§ Java libraries and interoperability
§ Standard monitoring tools
JRuby
require 'java'
java_import 'java.util.concurrent.ConcurrentHashMap'
map = ConcurrentHashMap.new
map['A'] = 123
map.put_if_absent('B', 456)
puts map
=> {"A"=>123, "B"=>456}
Java to Ruby
§ Asynchronous HTTP via Netty
§ Reactive Streams Support
§ Promises and Streams library
§ Works great with JRuby
§ Plugin Modules
§ Guice
§ Dropwizard Metrics
§ Etc.
Ratpack
RatpackServer.start do |server|
server.handlers do |chain|
chain.get do |ctx|
ctx.render(’Hello World!')
end
end
end
Starting a Server
§ Push-Pull based “stream” processing:
§ Non-blocking
§ Asynchronous
§ Potentially Unbounded
§ Non-blocking backpressure
§ JDK 9: java.util.concurrent.Flow
Reactive Streams
Promise
.value(@metric_registry)
.map(MetricRegistryJsonMapper.new(@alloc, MetricFilter::ALL))
.map { |buf| buf.to_string(Charset.default_charset) }
.map { |string| JSON.parse(string) }
.flat_map { |metric| send_event(metric) }
.then { |resp| Common::Log.debug "#{resp.status.code}" }
Example
§ Cluster management with Docker Engine
§ Task Scheduling and Scaling
§ Service Discovery
§ Load Balancing
§ Automatic Restart/Recovery
§ Rolling updates
Docker Swarm Mode
§ Cluster service that offers a REST API for scaling up and
down tasks
§ Automatically detects managed services in swarm
§ Supports
§ Preset scale increments/decrements
§ Cooldowns to avoid mistakes
Orbiter
Making a reactive system
Making a reactive system
Making a reactive system
Making a reactive system
Making a reactive system
Our System
HTTP POST
Market Updates
Stock Updates
Alerts/Rules
Notifications
SMS
DB Autoscaler
Cluster
Orbiter
HTTP POST
REST = Synchronous
Synchronous ≠ Reactive
How is this reactive?
§ Message Passing via HTTP POST
§ Service should limit blocking as much as possible
§ Return a Receipt for long processes
§ Communicate Backpressure via Status Codes (429)
§ Client decides how to handle messages if service is
unavailable
§ Buffering
§ Dropping
Reactive REST
§ HTTP is really nice because…
§ DNS and/or Service Discovery
§ Load Balancing
§ Transparent Scaling
§ Dynamic Routing and Proxies
Nothing wrong with Queues, but…
Challenge: Handling Uneven Load
§ Backpressure
§ Make the caller wait
§ Buffering
§ Accept the requests and send batches downstream
§ Caching
§ Accept the requests and send most recent downstream
Strategies
chain.post(stock') do |ctx|
http_client = ctx.get(HttpClient.java_class)
alert_service_client =
AlertServiceClient.new(ENV[’SA_ALERT_SERVICE_URL'],
http_client)
ctx.request.body
.map { |b| JSON.parse(b.text) }
.flat_map { |event| alert_service_client.send_event(event) }
.then { ctx.render('OK') }
end
Backpressure
Backpressure Demo
Buffering
chain.post(’stock') do |ctx|
buffer = ctx.get(EventBuffer.java_class)
ctx.request.body
.map { |b| JSON.parse(b.text) }
.flat_map { |event| buffer.add(event) }
.then do |buffered|
if buffered
ctx.render('OK')
else
Common::Log.debug 'backpressure!!!'
ctx.response.status(429).send
end
end
end
def add(event)
Promise.async do |d|
d.success(@buffer.offer(event, 1, TimeUnit::SECONDS))
end
end
def run
Execution.fork.start do |_|
get_events
.map { |events| reduce_events(events) }
.flat_map { |events| send_events(events) }
.defer(Duration.of_seconds(@backoff_duration))
.then do |responses|
responses.each { |response| handle_response(response) }
end
end
end
Buffering (contd)
Buffer Demo
Caching
chain.post(’stock') do |ctx|
cache = ctx.get(EventCache.java_class)
ctx.request.body
.map { |b| JSON.parse(b.text) }
.flat_map { |event| cache.add(event) }
.then do |cached|
if cached
ctx.render('OK')
else
Common::Log.debug 'backpressure!!!'
ctx.response.status(429).send
end
end
end
def add(event)
Promise.async do |d|
@cache.put(event['ticker'], event['price'])
@updates.put(event['ticker'], true)
d.success(true)
end
end
def run
Execution.fork.start do |_|
start = Time.now
get_events
.map { |keys| hydrate_events(keys) }
.flat_map { |events| send_events(events) }
.defer(Duration.of_seconds(@backoff_duration))
.then do |responses|
responses.each { |response| handle_response(response) }
end
end
end
Caching (contd)
Cache Demo
def backpressure(backoff)
if backoff
@metric_registry.meter('backpressure.service.alert').mark
@backoff_duration = [30, 1 + @backoff_duration * 2].min
puts "increasing back off to #{@backoff_duration} secs"
else
@backoff_duration = [@backoff_duration / 2, 1].max
if @backoff_duration > 1
puts "decreasing back off to #{@backoff_duration} secs"
else
@backoff_duration = 0
end
end
end
Backpressure
Cluster
Machine Machine Machine
Swarm Manager
orbiter
stock alert alertalert notif notif
scale db
Cluster
Machine Machine Machine
Swarm Manager
orbiter
stock alert alertalert notif notif
scale
Ingress traffic
Routed to Service
db
Cluster
Machine Machine Machine
Swarm Manager
orbiter
stock alert alertalert notif notif
scale
Ingress traffic
Routed to Service
db
Cluster
Machine Machine Machine
Swarm Manager
orbiter
stock
alert alertalert notif notif
scale
alert
Ingress traffic
Routed to Service
db
Monitoring Our Services
Scaling
def adjust_scale(metric_name, metric_value)
service = metric_name.split('.').last
Promise
.value(metric_value)
.next_op_if(
->(v) { v['m1_rate'] < 0.01 && v['m5_rate'] < 0.01 },
->(_) { scale_down(service) }
)
.next_op_if(
->(v) { v['m1_rate'] > 1 },
->(_) { scale_up(service) }
)
end
Scaling Up and Down
alert:
image: stockalert
command: bundle exec jruby ./alert_service/run.rb
networks:
- stockalert
deploy:
mode: replicated
replicas: 1
labels: [orbiter=true,orbiter.up=2,orbiter.cooldown=300]
…
Docker Scaling Configuration
Watch it in Action!
Scaling Up
Monitoring Effects of Scaling
Watch it in Action!
Scaling Down
Demo
HTTP POST
Market Updates
Stock Updates
Alerts/Rules
Notifications
SMS
DB Autoscaler
Cluster
Orbiter
HTTP POST
§ Joe Kutner, Deploying JRuby 9k
§ Joe Kutner, “Reactive Ruby: Building Real-time Apps with
JRuby and Ratpack”, http://blog.heroku.com
§ Dan Woods, Learning Ratpack
§ Jonas Bonér, Reactive Microservices Architecture
§ GitHub Project:
https://github.com/jscattergood/JavaOne_2017_CON3214
Further Reading
Autodesk and the Autodesk logo are registered trademarks or trademarks of Autodesk, Inc., and/or its subsidiaries and/or affiliates in the USA and/or other countries. All other brand names, product names, or trademarks belong to their respective holders.
Autodesk reserves the right to alter product and services offerings, and specifications and pricing at any time without notice, and is not responsible for typographical or graphical errors that may appear in this document.
© 2017 Autodesk. All rights reserved.

More Related Content

What's hot

Fighting Spam With A Perimeter Mail System 20071108 Sasag
Fighting Spam With A Perimeter Mail System 20071108 SasagFighting Spam With A Perimeter Mail System 20071108 Sasag
Fighting Spam With A Perimeter Mail System 20071108 Sasag
garrett honeycutt
 
초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기
OnGameServer
 

What's hot (20)

Fail over fail_back
Fail over fail_backFail over fail_back
Fail over fail_back
 
Scaling the Rails
Scaling the RailsScaling the Rails
Scaling the Rails
 
Fighting Spam With A Perimeter Mail System 20071108 Sasag
Fighting Spam With A Perimeter Mail System 20071108 SasagFighting Spam With A Perimeter Mail System 20071108 Sasag
Fighting Spam With A Perimeter Mail System 20071108 Sasag
 
초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기초보자를 위한 분산 캐시 이야기
초보자를 위한 분산 캐시 이야기
 
92 grand prix_2013
92 grand prix_201392 grand prix_2013
92 grand prix_2013
 
A Comprehensive Guide for DNS Cluster Configurations
A Comprehensive Guide for DNS Cluster ConfigurationsA Comprehensive Guide for DNS Cluster Configurations
A Comprehensive Guide for DNS Cluster Configurations
 
Beyond Best Practice: Grid Computing in the Modern World
Beyond Best Practice: Grid Computing in the Modern World Beyond Best Practice: Grid Computing in the Modern World
Beyond Best Practice: Grid Computing in the Modern World
 
Production MongoDB in the Cloud
Production MongoDB in the CloudProduction MongoDB in the Cloud
Production MongoDB in the Cloud
 
Feed Burner Scalability
Feed Burner ScalabilityFeed Burner Scalability
Feed Burner Scalability
 
Resilient design 101 (BuildStuff LT 2017)
Resilient design 101 (BuildStuff LT 2017)Resilient design 101 (BuildStuff LT 2017)
Resilient design 101 (BuildStuff LT 2017)
 
Resilient Design 101 (JeeConf 2017)
Resilient Design 101 (JeeConf 2017)Resilient Design 101 (JeeConf 2017)
Resilient Design 101 (JeeConf 2017)
 
Continuent webinar 02-19-2015
Continuent webinar 02-19-2015Continuent webinar 02-19-2015
Continuent webinar 02-19-2015
 
GC free coding in @Java presented @Geecon
GC free coding in @Java presented @GeeconGC free coding in @Java presented @Geecon
GC free coding in @Java presented @Geecon
 
Sql saturday dc vm ware
Sql saturday dc vm wareSql saturday dc vm ware
Sql saturday dc vm ware
 
ESX performance problems 10 steps
ESX performance problems 10 stepsESX performance problems 10 steps
ESX performance problems 10 steps
 
Low latency for high throughput
Low latency for high throughputLow latency for high throughput
Low latency for high throughput
 
Low level java programming
Low level java programmingLow level java programming
Low level java programming
 
Adminblast 2013
Adminblast 2013Adminblast 2013
Adminblast 2013
 
Troubleshooting Apache Cloudstack
Troubleshooting Apache CloudstackTroubleshooting Apache Cloudstack
Troubleshooting Apache Cloudstack
 
Automating the Entire PostgreSQL Lifecycle
Automating the Entire PostgreSQL Lifecycle Automating the Entire PostgreSQL Lifecycle
Automating the Entire PostgreSQL Lifecycle
 

Similar to Reactive Microservices with JRuby and Docker

Similar to Reactive Microservices with JRuby and Docker (20)

Load testing with Blitz
Load testing with BlitzLoad testing with Blitz
Load testing with Blitz
 
How lagom helps to build real world microservice systems
How lagom helps to build real world microservice systemsHow lagom helps to build real world microservice systems
How lagom helps to build real world microservice systems
 
Microservices Manchester: How Lagom Helps to Build Real World Microservice Sy...
Microservices Manchester: How Lagom Helps to Build Real World Microservice Sy...Microservices Manchester: How Lagom Helps to Build Real World Microservice Sy...
Microservices Manchester: How Lagom Helps to Build Real World Microservice Sy...
 
Reactive programming with examples
Reactive programming with examplesReactive programming with examples
Reactive programming with examples
 
Reactor, Reactive streams and MicroServices
Reactor, Reactive streams and MicroServicesReactor, Reactive streams and MicroServices
Reactor, Reactive streams and MicroServices
 
The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016The Road To Reactive with RxJava JEEConf 2016
The Road To Reactive with RxJava JEEConf 2016
 
Container orchestration from theory to practice
Container orchestration from theory to practiceContainer orchestration from theory to practice
Container orchestration from theory to practice
 
Microservice Come in Systems
Microservice Come in SystemsMicroservice Come in Systems
Microservice Come in Systems
 
Scaling asp.net websites to millions of users
Scaling asp.net websites to millions of usersScaling asp.net websites to millions of users
Scaling asp.net websites to millions of users
 
Low latency in java 8 by Peter Lawrey
Low latency in java 8 by Peter Lawrey Low latency in java 8 by Peter Lawrey
Low latency in java 8 by Peter Lawrey
 
Deploying your web application with AWS ElasticBeanstalk
Deploying your web application with AWS ElasticBeanstalkDeploying your web application with AWS ElasticBeanstalk
Deploying your web application with AWS ElasticBeanstalk
 
Two Years, Zero servers: Lessons learned from running a startup 100% on Serve...
Two Years, Zero servers: Lessons learned from running a startup 100% on Serve...Two Years, Zero servers: Lessons learned from running a startup 100% on Serve...
Two Years, Zero servers: Lessons learned from running a startup 100% on Serve...
 
Akka (BeJUG)
Akka (BeJUG)Akka (BeJUG)
Akka (BeJUG)
 
les07.pdf
les07.pdfles07.pdf
les07.pdf
 
Building Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJavaBuilding Scalable Stateless Applications with RxJava
Building Scalable Stateless Applications with RxJava
 
Above the clouds: introducing Akka
Above the clouds: introducing AkkaAbove the clouds: introducing Akka
Above the clouds: introducing Akka
 
Springone2gx 2014 Reactive Streams and Reactor
Springone2gx 2014 Reactive Streams and ReactorSpringone2gx 2014 Reactive Streams and Reactor
Springone2gx 2014 Reactive Streams and Reactor
 
Serverless Multi Region Cache Replication
Serverless Multi Region Cache ReplicationServerless Multi Region Cache Replication
Serverless Multi Region Cache Replication
 
DevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on KubernetesDevoxxUK: Optimizating Application Performance on Kubernetes
DevoxxUK: Optimizating Application Performance on Kubernetes
 
Introduction to LAVA Workload Scheduler
Introduction to LAVA Workload SchedulerIntroduction to LAVA Workload Scheduler
Introduction to LAVA Workload Scheduler
 

Recently uploaded

TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
mohitmore19
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
VictorSzoltysek
 

Recently uploaded (20)

%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
%in kaalfontein+277-882-255-28 abortion pills for sale in kaalfontein
 
Microsoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdfMicrosoft AI Transformation Partner Playbook.pdf
Microsoft AI Transformation Partner Playbook.pdf
 
Exploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdfExploring the Best Video Editing App.pdf
Exploring the Best Video Editing App.pdf
 
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456LEVEL 5   - SESSION 1 2023 (1).pptx - PDF 123456
LEVEL 5 - SESSION 1 2023 (1).pptx - PDF 123456
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students8257 interfacing 2 in microprocessor for btech students
8257 interfacing 2 in microprocessor for btech students
 
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdfLearn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
Learn the Fundamentals of XCUITest Framework_ A Beginner's Guide.pdf
 
AI & Machine Learning Presentation Template
AI & Machine Learning Presentation TemplateAI & Machine Learning Presentation Template
AI & Machine Learning Presentation Template
 
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICECHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
CHEAP Call Girls in Pushp Vihar (-DELHI )🔝 9953056974🔝(=)/CALL GIRLS SERVICE
 
Software Quality Assurance Interview Questions
Software Quality Assurance Interview QuestionsSoftware Quality Assurance Interview Questions
Software Quality Assurance Interview Questions
 
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verifiedSector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
Sector 18, Noida Call girls :8448380779 Model Escorts | 100% verified
 
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) SolutionIntroducing Microsoft’s new Enterprise Work Management (EWM) Solution
Introducing Microsoft’s new Enterprise Work Management (EWM) Solution
 
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
The Guide to Integrating Generative AI into Unified Continuous Testing Platfo...
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
Pharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodologyPharm-D Biostatistics and Research methodology
Pharm-D Biostatistics and Research methodology
 
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park %in kempton park+277-882-255-28 abortion pills for sale in kempton park
%in kempton park+277-882-255-28 abortion pills for sale in kempton park
 
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdfThe Ultimate Test Automation Guide_ Best Practices and Tips.pdf
The Ultimate Test Automation Guide_ Best Practices and Tips.pdf
 
Define the academic and professional writing..pdf
Define the academic and professional writing..pdfDefine the academic and professional writing..pdf
Define the academic and professional writing..pdf
 
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
Crypto Cloud Review - How To Earn Up To $500 Per DAY Of Bitcoin 100% On AutoP...
 
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM TechniquesAI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
AI Mastery 201: Elevating Your Workflow with Advanced LLM Techniques
 

Reactive Microservices with JRuby and Docker

  • 1. © 2017 Autodesk John Scattergood Senior Principal Engineer JavaOne 2017 Reactive Microservices with JRuby and Docker
  • 2. § Engineer at Autodesk § Enjoy coding in Java, Ruby, Groovy and JavaScript § Run JRuby apps in production that serve millions of requests/day § First time JavaOne Speaker @johnscattergood About Me
  • 4. Our System Market Updates Stock Updates Alerts/Rules Notifications SMS DB Autoscaler Cluster Scale
  • 5. § Price Alerts (eCommerce) § APM and Infrastructure Monitoring (IT) § Fraud Detection (Credit) § Devices, Transponders, etc. (IOT) Other Domains
  • 7. § Dynamic § Object-oriented w/ first class functions § Expressive § Flexible § Easy to learn Ruby Ruby is simple in appearance, but is very complex inside just like our human body - Yukihiro “Matz” Matsumoto Ruby Creator
  • 8. @memo = { 1 => 1, 2 => 2 } def fib(n) @memo[n] ||= fib(n - 1) + fib(n - 2) end fib(100) => 573147844013817084101 Fibonnaci
  • 9. § Fully compatible implementation of Ruby § Includes benefits of JVM § High Performance § True multi-threading § Java libraries and interoperability § Standard monitoring tools JRuby
  • 10. require 'java' java_import 'java.util.concurrent.ConcurrentHashMap' map = ConcurrentHashMap.new map['A'] = 123 map.put_if_absent('B', 456) puts map => {"A"=>123, "B"=>456} Java to Ruby
  • 11. § Asynchronous HTTP via Netty § Reactive Streams Support § Promises and Streams library § Works great with JRuby § Plugin Modules § Guice § Dropwizard Metrics § Etc. Ratpack
  • 12. RatpackServer.start do |server| server.handlers do |chain| chain.get do |ctx| ctx.render(’Hello World!') end end end Starting a Server
  • 13. § Push-Pull based “stream” processing: § Non-blocking § Asynchronous § Potentially Unbounded § Non-blocking backpressure § JDK 9: java.util.concurrent.Flow Reactive Streams
  • 14. Promise .value(@metric_registry) .map(MetricRegistryJsonMapper.new(@alloc, MetricFilter::ALL)) .map { |buf| buf.to_string(Charset.default_charset) } .map { |string| JSON.parse(string) } .flat_map { |metric| send_event(metric) } .then { |resp| Common::Log.debug "#{resp.status.code}" } Example
  • 15. § Cluster management with Docker Engine § Task Scheduling and Scaling § Service Discovery § Load Balancing § Automatic Restart/Recovery § Rolling updates Docker Swarm Mode
  • 16. § Cluster service that offers a REST API for scaling up and down tasks § Automatically detects managed services in swarm § Supports § Preset scale increments/decrements § Cooldowns to avoid mistakes Orbiter
  • 22. Our System HTTP POST Market Updates Stock Updates Alerts/Rules Notifications SMS DB Autoscaler Cluster Orbiter HTTP POST
  • 23. REST = Synchronous Synchronous ≠ Reactive How is this reactive?
  • 24. § Message Passing via HTTP POST § Service should limit blocking as much as possible § Return a Receipt for long processes § Communicate Backpressure via Status Codes (429) § Client decides how to handle messages if service is unavailable § Buffering § Dropping Reactive REST
  • 25. § HTTP is really nice because… § DNS and/or Service Discovery § Load Balancing § Transparent Scaling § Dynamic Routing and Proxies Nothing wrong with Queues, but…
  • 27. § Backpressure § Make the caller wait § Buffering § Accept the requests and send batches downstream § Caching § Accept the requests and send most recent downstream Strategies
  • 28. chain.post(stock') do |ctx| http_client = ctx.get(HttpClient.java_class) alert_service_client = AlertServiceClient.new(ENV[’SA_ALERT_SERVICE_URL'], http_client) ctx.request.body .map { |b| JSON.parse(b.text) } .flat_map { |event| alert_service_client.send_event(event) } .then { ctx.render('OK') } end Backpressure
  • 30. Buffering chain.post(’stock') do |ctx| buffer = ctx.get(EventBuffer.java_class) ctx.request.body .map { |b| JSON.parse(b.text) } .flat_map { |event| buffer.add(event) } .then do |buffered| if buffered ctx.render('OK') else Common::Log.debug 'backpressure!!!' ctx.response.status(429).send end end end
  • 31. def add(event) Promise.async do |d| d.success(@buffer.offer(event, 1, TimeUnit::SECONDS)) end end def run Execution.fork.start do |_| get_events .map { |events| reduce_events(events) } .flat_map { |events| send_events(events) } .defer(Duration.of_seconds(@backoff_duration)) .then do |responses| responses.each { |response| handle_response(response) } end end end Buffering (contd)
  • 33. Caching chain.post(’stock') do |ctx| cache = ctx.get(EventCache.java_class) ctx.request.body .map { |b| JSON.parse(b.text) } .flat_map { |event| cache.add(event) } .then do |cached| if cached ctx.render('OK') else Common::Log.debug 'backpressure!!!' ctx.response.status(429).send end end end
  • 34. def add(event) Promise.async do |d| @cache.put(event['ticker'], event['price']) @updates.put(event['ticker'], true) d.success(true) end end def run Execution.fork.start do |_| start = Time.now get_events .map { |keys| hydrate_events(keys) } .flat_map { |events| send_events(events) } .defer(Duration.of_seconds(@backoff_duration)) .then do |responses| responses.each { |response| handle_response(response) } end end end Caching (contd)
  • 36. def backpressure(backoff) if backoff @metric_registry.meter('backpressure.service.alert').mark @backoff_duration = [30, 1 + @backoff_duration * 2].min puts "increasing back off to #{@backoff_duration} secs" else @backoff_duration = [@backoff_duration / 2, 1].max if @backoff_duration > 1 puts "decreasing back off to #{@backoff_duration} secs" else @backoff_duration = 0 end end end Backpressure
  • 37. Cluster Machine Machine Machine Swarm Manager orbiter stock alert alertalert notif notif scale db
  • 38. Cluster Machine Machine Machine Swarm Manager orbiter stock alert alertalert notif notif scale Ingress traffic Routed to Service db
  • 39. Cluster Machine Machine Machine Swarm Manager orbiter stock alert alertalert notif notif scale Ingress traffic Routed to Service db
  • 40. Cluster Machine Machine Machine Swarm Manager orbiter stock alert alertalert notif notif scale alert Ingress traffic Routed to Service db
  • 43. def adjust_scale(metric_name, metric_value) service = metric_name.split('.').last Promise .value(metric_value) .next_op_if( ->(v) { v['m1_rate'] < 0.01 && v['m5_rate'] < 0.01 }, ->(_) { scale_down(service) } ) .next_op_if( ->(v) { v['m1_rate'] > 1 }, ->(_) { scale_up(service) } ) end Scaling Up and Down
  • 44. alert: image: stockalert command: bundle exec jruby ./alert_service/run.rb networks: - stockalert deploy: mode: replicated replicas: 1 labels: [orbiter=true,orbiter.up=2,orbiter.cooldown=300] … Docker Scaling Configuration
  • 45. Watch it in Action! Scaling Up
  • 47. Watch it in Action! Scaling Down
  • 48. Demo HTTP POST Market Updates Stock Updates Alerts/Rules Notifications SMS DB Autoscaler Cluster Orbiter HTTP POST
  • 49. § Joe Kutner, Deploying JRuby 9k § Joe Kutner, “Reactive Ruby: Building Real-time Apps with JRuby and Ratpack”, http://blog.heroku.com § Dan Woods, Learning Ratpack § Jonas Bonér, Reactive Microservices Architecture § GitHub Project: https://github.com/jscattergood/JavaOne_2017_CON3214 Further Reading
  • 50. Autodesk and the Autodesk logo are registered trademarks or trademarks of Autodesk, Inc., and/or its subsidiaries and/or affiliates in the USA and/or other countries. All other brand names, product names, or trademarks belong to their respective holders. Autodesk reserves the right to alter product and services offerings, and specifications and pricing at any time without notice, and is not responsible for typographical or graphical errors that may appear in this document. © 2017 Autodesk. All rights reserved.