Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Scaling Node.js Applications with Redis, RabbitMQ and cote.js

JSIST
September 27, 2014

Scaling Node.js Applications with Redis, RabbitMQ and cote.js

JSIST 2014
By : Armağan Amcalar
http://jsist.org

JSIST

September 27, 2014
Tweet

More Decks by JSIST

Other Decks in Programming

Transcript

  1. WHO AM I? Armagan Amcalar Co-founder, Chief Software Architect dashersw

    Startup Kitchen AUTHORED ON GITHUB pedalboard.js tartJS geneJS cote semaver jira-bot HOBBY PROJECTS pedals.io trax.io
  2. NODE.JS We love it. We develop all kinds of software

    with it. We love to daemonize it.
  3. THE PROBLEM It doesn't scale well. Programming model encourages stateful

    app design Works great as single process Works OK as a cluster
  4. NGINX Easy to set up if you're familiar with nginx

    Hard to maintain Yet another technology dependency NODE-HTTP-PROXY Hard to set up even if you're familiar Hard to maintain Very low level
  5. WE NEED A DIFFERENT SOLUTION. Because we have more problems

    We're not just building express apps We were programming the DOM, we need that flexibility
  6. MORE PROBLEMS? Be fast with your API response Asynchronous processing

    (e.g., analytics) You may need to scale very dynamically Fault tolerance THE YEAR'S 2014, WHERE ARE THE EVENTS?
  7. MONOLITHIC APPLICATIONS Single code base One process to rule them

    all A bug anywhere crashes the whole system May consume lots of stale resources Hard to scale; needs even more stale resources Request–response flow is one huge piece Easy to manage
  8. MICROSERVICES Separate code base Multi processes for each service A

    bug in a service crashes only that service Consumes minimal resources Scales well, needs minimal additional resources Supports event-driven architecture Request–response flow breakdown Hard to manage
  9. PUB-SUB PATTERN Just like DOM events, what we're used to

    build. Instead of click events, you have custom events (e.g. in jQuery) Instead of DOM element interaction, you have daemon interaction
  10. OBSERVER PATTERN First-of-its-kind event driven pattern You an object property,

    not an arbitrary event Like all your click handlers have to have the same name Limits possibilities
  11. ENTER REDIS Originally a NoSQL database Key-value pair server with

    lots of great features like sets, etc. Pub-sub capability Supports events based on channels and patterns Very cool node.js library
  12. A REDIS PUBSUB-BASED ARCHITECTURE redis d1 d4 d3 d2 publishes

    foo notifies of foo notifies of foo notifies of foo client request session storage logs API
  13. EXAMPLE var redis = require('redis'), client = redis.createClient(6379, '127.0.0.1'); client.publish('request',

    JSON.stringify({ body: 'some cool request' })); var redis = require('redis'), logger = redis.createClient(6379, '127.0.0.1'); logger.subscribe('request'); logger.on('message', function(channel, message) { if (channel == 'request') console.log(JSON.parse(message)); }); Client Logger
  14. ENTER RABBITMQ A message broker for distributed applications Like redis

    pubsub, with heavy focus on additional features such as flexible message routing work queues, topics, etc. QoS management round robin load balancing message acks rate limiting unfriendly node.js library
  15. EXAMPLE WORK QUEUE var amqp = require('amqp'), connection = amqp.createConnection(),

    workId = 0; connection.on('ready', function() { connection.queue('work_queue', {autoDelete: false, durable: true}, function(queue) { setInterval(function() { connection.publish('work_queue', 'message #' + ++workId, { deliveryMode: 2 }); console.log('sent message #' + workId); }, 1000); }); }); var amqp = require('amqp'), connection = amqp.createConnection(); connection.on('ready', function () { connection.queue('work_queue', {autoDelete: false, durable: true}, function(queue) { queue.subscribe({ack: true, prefetchCount: 1}, function(msg) { var body = msg.data.toString('utf-8'); console.log("received", body); queue.shift(); // basic_ack equivalent }); }); });
  16. COTE.JS FEATURES auto-discovery mesh network, peer-to-peer communication pubsub pattern requester/responder

    pattern client-side communication with websockets load balancing with different strategies daemon monitor
  17. EXAMPLE PUB-SUB IMPLEMENTATION var Publisher = require('cote').Publisher, publisher = new

    Publisher({ name: 'publisher', broadcasts: ['update'] }), workId = 0; publisher.on('ready', function() { setInterval(function() { console.log('emitting', ++workId); publisher.publish('update', workId); }, 3000); }); var Subscriber = require('cote').Subscriber, subscriber = new Subscriber({ name: 'subscriber' }); subscriber.on('update', function(message) { console.log('update', message); });
  18. CONCLUSION With Redis, RabbitMQ or cote.js we can; Apply sophisticated

    programming paradigms Scale nearly infinitely Have fault-tolerant systems
  19. THANK YOU! CONTRIBUTE TO COTE.JS github.com/dashersw/cote LET'S KEEP IN TOUCH!

    Armagan Amcalar twitter: github: blog: [email protected] @aamcalar dashersw arm.ag examples at https://github.com/dashersw/node-scale