Scale Node

Embed Size (px)

Citation preview

  • 8/10/2019 Scale Node

    1/30

    SCALING NODE.JSAPPLICATIONS WITH

    REDIS, RABBITMQ & COTE.JS

    Armagan AmcalarJSIST 2014, Istanbul

    Sep 27th, 2014

  • 8/10/2019 Scale Node

    2/30

    WHO AM I?

    Armagan AmcalarCo-founder, Chief Software Architect

    dashersw

    Startup Kitchen

    AUTHORED ON GITHUB

    pedalboard.js

    tartJS

    geneJS

    cote

    semaver

    jira-bot

    HOBBY PROJECTS

    pedals.io

    trax.io

  • 8/10/2019 Scale Node

    3/30

    NODE.JS

    We love it.

    We develop all kinds of software with it.

    We love to daemonize it.

  • 8/10/2019 Scale Node

    4/30

    THE PROBLEMIt doesn't scale well.

    Programming model encourages stateful app design

    Works great as single process

    Works OK as a cluster

  • 8/10/2019 Scale Node

    5/30

    WHAT'S NEXT?What if you need more computing power?

    How about horizontal scalability?

  • 8/10/2019 Scale Node

    6/30

    CURRENT SOLUTION

    NGINX

    NODE-HTTP-PROXY

    REVERSE PROXY

  • 8/10/2019 Scale Node

    7/30

    NGINXEasy to set up if you're familiar

    with nginx

    Hard to maintain

    Yet another technology

    dependency

    NODE-HTTP-PROXYHard to set up even if you're

    familiar

    Hard to maintain

    Very low level

  • 8/10/2019 Scale Node

    8/30

    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

  • 8/10/2019 Scale Node

    9/30

    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?

  • 8/10/2019 Scale Node

    10/30

  • 8/10/2019 Scale Node

    11/30

  • 8/10/2019 Scale Node

    12/30

    MICROSERVICESSeparate 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

    Requestresponse flow breakdown

    Hard to manage

  • 8/10/2019 Scale Node

    13/30

    EVENT-DRIVEN ARCHITECTURE

    PUB-SUB PATTERNOBSERVER PATTERN

  • 8/10/2019 Scale Node

    14/30

    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

  • 8/10/2019 Scale Node

    15/30

    OBSERVER PATTERNFirst-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

  • 8/10/2019 Scale Node

    16/30

    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

  • 8/10/2019 Scale Node

    17/30

    A REDIS PUBSUB-BASED ARCHITECTURE

    redisd1

    d4

    d3

    d2

    publishes foo

    notifies of foo

    notifies of foo

    notifies of foo

    client request

    session storage

    logs

    API

  • 8/10/2019 Scale Node

    18/30

    EXAMPLE

    varredis = require('redis'),

    client = redis.createClient(6379, '127.0.0.1');

    client.publish('request', JSON.stringify({

    body: 'some cool request'

    }));

    varredis = 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

  • 8/10/2019 Scale Node

    19/30

    QUICK DEMO

  • 8/10/2019 Scale Node

    20/30

    ENTER RABBITMQA 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

  • 8/10/2019 Scale Node

    21/30

    WORK QUEUES

    REMOTE PROCEDURE CALLS

  • 8/10/2019 Scale Node

    22/30

    EXAMPLE WORK QUEUEvaramqp = 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);

    });

    });

    varamqp = 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) {

    varbody = msg.data.toString('utf-8');

    console.log("received", body);

    queue.shift(); // basic_ack equivalent

    });

    });

    });

  • 8/10/2019 Scale Node

    23/30

    QUICK DEMO

  • 8/10/2019 Scale Node

    24/30

    ENTER COTE.JSnode.js framework for fault tolerant, distributed apps

    developed at Startup Kitchenpartially funded by TUBITAK

  • 8/10/2019 Scale Node

    25/30

    COTE.JS FEATURES

    auto-discovery

    mesh network, peer-to-peer communication

    pubsub pattern

    requester/responder patternclient-side communication with websockets

    load balancing with different strategies

    daemon monitor

  • 8/10/2019 Scale Node

    26/30

    EXAMPLE ARCHITECTURE

  • 8/10/2019 Scale Node

    27/30

    EXAMPLE PUB-SUB IMPLEMENTATIONvarPublisher = require('cote').Publisher,

    publisher = newPublisher({

    name: 'publisher',

    broadcasts: ['update']

    }),

    workId = 0;

    publisher.on('ready', function() {

    setInterval(function() {

    console.log('emitting', ++workId);

    publisher.publish('update', workId);

    }, 3000);});

    varSubscriber = require('cote').Subscriber,

    subscriber = newSubscriber({

    name: 'subscriber'

    });

    subscriber.on('update', function(message) {

    console.log('update', message);

    });

  • 8/10/2019 Scale Node

    28/30

    QUICK DEMO

  • 8/10/2019 Scale Node

    29/30

    CONCLUSION

    With Redis, RabbitMQ or cote.js we can;

    Apply sophisticated programming paradigmsScale nearly infinitely

    Have fault-tolerant systems

  • 8/10/2019 Scale Node

    30/30

    THANK YOU!

    CONTRIBUTE TO COTE.JS

    github.com/dashersw/cote

    LET'S KEEP IN TOUCH!

    Armagan Amcalar

    twitter:github:

    blog:

    [email protected]

    @aamcalardashersw

    arm.ag

    examples at https://github.com/dashersw/node-scale