+ All Categories
Home > Technology > From node.js to Scala - with a 100x performance boost

From node.js to Scala - with a 100x performance boost

Date post: 13-Feb-2017
Category:
Upload: itamar-ravid
View: 398 times
Download: 0 times
Share this document with a friend
50
FROM TO with a 100x perf. boost! BY ITAMAR RAVID | MAY 3, 2016
Transcript
Page 1: From node.js to Scala - with a 100x performance boost

FROM TO with a 100x perf. boost!

BY ITAMAR RAVID | MAY 3, 2016

Page 2: From node.js to Scala - with a 100x performance boost

t

AGENDA

WE’LL TALK ABOUT…

• What we do, our challenges and what led us to Scala and Akka;

• How we redesigned our core data processing service;

• Some useful lessons and patterns.

There will be relatively little node.js bashing. Promise.

Page 3: From node.js to Scala - with a 100x performance boost

t

BIGPANDA: THE ANSWER TO ALERT FATIGUE

RABBIT IS DOWN!NO FREE SPACE!

INBOUND QUEUE OVERFLOWING!OUTBOUND QUEUE OVERFLOWING!

APPLICATION HEALTH CRITICAL!TOO MANY FAILED HTTP REQS!

rabbit-1, ping

rabbit-2, disk

queue-1, size

queue-2, size

app1, health

app2, 500 codes

RabbitMQ cluster

ping disk

RabbitMQ node 3

queue size queue size

API server

health failed reqs

Correlation A

lgorithm

Page 4: From node.js to Scala - with a 100x performance boost

t

CorrelationStage

NormalizationStage

IN TERMS OF STREAMS…

RABBIT IS DOWN!NO FREE SPACE!

INBOUND QUEUE OVERFLOWING!OUTBOUND QUEUE OVERFLOWING!

APPLICATION HEALTH CRITICAL!TOO MANY FAILED HTTP REQS!

Nagios event source

Datadog event source

AppDynamics event source

rabbit-1, ping

rabbit-2, disk

queue-1, size

queue-2, size

app1, health

app2, 500 codes

RabbitMQ cluster

ping disk

RabbitMQ node 3

queue size queue size

API server

health failed reqs

Correlation A

lgorithm

Page 5: From node.js to Scala - with a 100x performance boost

CHALLENGE 1 SCALING TO MEET CUSTOMER LOAD

Page 6: From node.js to Scala - with a 100x performance boost

t

HIGH-LEVEL ARCHITECTURE

API servers

API servers

API servers

Normalization Correlation

Correlation

Correlation

RabbitMQ Exchange Normalization

Normalization

RabbitMQ Exchange

Mongo

RabbitMQ Exchange

Page 7: From node.js to Scala - with a 100x performance boost

t

USAGE OF RABBITMQ

Correlation

Correlation

Correlation

RabbitMQ Cons. Hash

Queue (Customers A, B, C)

Queue (Customers D, E, F)

Queue (Customers X, Y, Z)

Route byhash on

Customer

DATA FOR A GIVEN CUSTOMER MUST BE PROCESSED SERIALLY,

IN ORDER. SO…

Page 8: From node.js to Scala - with a 100x performance boost

t

(ALERT) STORMS

Page 9: From node.js to Scala - with a 100x performance boost

t

MEET REALITY!

Not fun!

A hiccup in a customer’s datacenter =>An entire queue is blocked

Page 10: From node.js to Scala - with a 100x performance boost

CHALLENGE 2 CORRELATION PREVIEW

Page 11: From node.js to Scala - with a 100x performance boost

t

CORRELATION

Same host, 4 hours …

MATCHING RULES

+

INCIDENTrabbit-1

ping disk

rabbit-1, ping, t=5

rabbit-1, disk, t=7

Page 12: From node.js to Scala - with a 100x performance boost

t

CORRELATION

MATCHING RULES

+

INCIDENTrabbit-1

ping disk

Same host, 4 hours 30 minutes

rabbit-1, ping, t=5

rabbit-1, disk, t=7

Page 13: From node.js to Scala - with a 100x performance boost

t

CORRELATION

MATCHING RULES

+

INCIDENT

rabbit-1, ping, t=5

rabbit-1, disk, t=7

Same host, 4 hours 30 minutes

?

Page 14: From node.js to Scala - with a 100x performance boost

t

A CORRELATION TIME-MACHINE

1 2 3 4 5 6 7 8 9 N…10

ALERTS WE’RE HERE

START FROM HERE (DC OUTAGE)

CorrelationServers

OFFSETS

Page 15: From node.js to Scala - with a 100x performance boost

t

THIS MEANS…

REPLAY DETERMINISTICFAST

Page 16: From node.js to Scala - with a 100x performance boost

SOLUTIONS!

Page 17: From node.js to Scala - with a 100x performance boost

t

EXISTING CORRELATION SOLUTION

Processing Stage

Mongo

RabbitRabbit RabbitRabbit Processing Stage

Processing Stage

PROCESSING STAGE - A NODE.JS CALLBACK.

Shared mutable state

No isolation

No replay

Page 18: From node.js to Scala - with a 100x performance boost

t

DESIRED SOLUTION

Processing Stage RabbitRabbit Processing

Stage

Mongo

Processing Stage

Page 19: From node.js to Scala - with a 100x performance boost

t

NODE.JS - PLATFORM LIMITATIONS

HEAP SIZE - LIMITED TO 1.7GB

SINGLE THREADED :-(

TypeError: undefined is not a function

Page 20: From node.js to Scala - with a 100x performance boost

t

COMPONENTS

DURABLE EVENT STREAM

PLATFORM

COMPUTING FRAMEWORK

Page 21: From node.js to Scala - with a 100x performance boost

t

ACTOR-BASED SOLUTION

Node Manager

Customer A Pipeline

KafkaReader

Algorithmrunner

MongoWriter

RabbitWriter

Customer B Pipeline

Customer C Pipeline

SUPERVISION

MESSAGING

customer_a_inputs

Page 22: From node.js to Scala - with a 100x performance boost

t

NEXT-GEN SOLUTION

Node Manager

Customer A Pipeline

KafkaReader

Algorithm runner

MongoWriter

RabbitWriter

Customer B Pipeline

Customer C Pipeline

SUPERVISION

MESSAGING

FAILURE

ISOLATION

customer_a_inputs

Page 23: From node.js to Scala - with a 100x performance boost

t

NEXT-GEN SOLUTION

Node Manager

Customer A Pipeline

KafkaReader

Algorithmrunner

MongoWriter

RabbitWriter

Customer B Pipeline

Customer C Pipeline

SUPERVISION

MESSAGING

SEPARATE DISPATCHERS

FOR QOS-TUNING

customer_a_inputs

Page 24: From node.js to Scala - with a 100x performance boost

t

SCALING OUT

Node 1

ClusterManager

Node Manager

Node 2

Node Manager

Node 3

Node Manager

Page 25: From node.js to Scala - with a 100x performance boost

LESSONS LEARNED

Page 26: From node.js to Scala - with a 100x performance boost

t

PRUNING AN INFINITE DATA STREAM

1 2 3 4 5 6 7 8 9 N…10

Page 27: From node.js to Scala - with a 100x performance boost

t

PRUNING AN INFINITE DATA STREAM

1 2 3 4 5 6 7 8 9 N…10

t=10, Critical t=8, OK

Page 28: From node.js to Scala - with a 100x performance boost

t

PRUNING AN INFINITE DATA STREAM

5 6 7 8 9 N…10

t=8, OK

MISSING ALERTS :-(

PRUNING STREAMS THAT RESULT IN STATE REQUIRES STATE RECOVERY.

Page 29: From node.js to Scala - with a 100x performance boost

t

PRUNING AN INFINITE DATA STREAM

5 6 7 8 9 N…10

Snapshot Repository

<data …> lastOffset: 4

<data …> lastOffset: 8

<data …> lastOffset: 10

ON BOOT, LATEST SNAPSHOT IS LOADED

AND STREAM IS SEEKED TO STORED OFFSET.

Page 30: From node.js to Scala - with a 100x performance boost

t

PRUNING AN INFINITE DATA STREAM

CHALLENGES: - COMPACTNESS - SCHEMA EVOLUTION

kryo/chill with a manual de/serializer <=> Map[String, Any]

Schema evolution support with some caveats

Big datasets are only a few MBs in size

Page 31: From node.js to Scala - with a 100x performance boost

USE SNAPSHOTS TO PRUNE STREAMS

JSON IS NOT THE ONLY SOLUTION!

KEY TAKEAWAYS

Page 32: From node.js to Scala - with a 100x performance boost

t

FAULT-TOLERANCE THROUGH BEHAVIORAL TRAITS

INPUTS

MSG BATCHES

Kafka reader

Algorithm Runner

MongoWriter

RabbitWriter

Page 33: From node.js to Scala - with a 100x performance boost

t

FAULT-TOLERANCE THROUGH BEHAVIORAL TRAITS

INPUTS

MSG BATCHES1

PIPELINING BETWEEN STAGES

Kafka reader

Algorithm Runner

MongoWriter

RabbitWriter

Page 34: From node.js to Scala - with a 100x performance boost

t

FAULT-TOLERANCE THROUGH BEHAVIORAL TRAITS

INPUTS

MSG BATCHES2 1

PIPELINING BETWEEN STAGES

Kafka reader

Algorithm Runner

MongoWriter

RabbitWriter

Page 35: From node.js to Scala - with a 100x performance boost

t

FAULT-TOLERANCE THROUGH BEHAVIORAL TRAITS

INPUTS

MSG BATCHES3 2 1

PIPELINING BETWEEN STAGES

Kafka reader

Algorithm Runner

MongoWriter

RabbitWriter

Page 36: From node.js to Scala - with a 100x performance boost

t

FAULT-TOLERANCE THROUGH BEHAVIORAL TRAITS

Kafka reader

Algorithm Runner

MongoWriter

RabbitWriter

INPUTS

MSG BATCHES3 2 1

PIPELINING BETWEEN STAGES

RETRYING

Persistent failurewill restart entire

pipeline

Page 37: From node.js to Scala - with a 100x performance boost

t

FAULT-TOLERANCE THROUGH BEHAVIORAL TRAITS

INPUTS

MSG BATCHES4 3 2 1

PIPELINING BETWEEN STAGES

RETRYING

Kafka reader

Algorithm Runner

MongoWriter

RabbitWriter

Page 38: From node.js to Scala - with a 100x performance boost

t

FAULT-TOLERANCE THROUGH BEHAVIORAL TRAITS

INPUTS

MSG BATCHES4 3 2 1

PIPELINING BETWEEN STAGES

RETRYING

Kafka reader

Algorithm Runner

MongoWriter

RabbitWriter

Page 39: From node.js to Scala - with a 100x performance boost

CAPTURE COMMON ACTOR

BEHAVIOR USING TRAITS

(BUT MAKE SURE THEY COMPOSE!)

KEY TAKEAWAYS

Page 40: From node.js to Scala - with a 100x performance boost

t

DEFERRING AND CONTROLLING STATE MUTATION

PREVIOUSLY:

Processing Stage

Mongo

Processing Stage

Processing Stage

HERE BE RACE CONDITIONS!

Page 41: From node.js to Scala - with a 100x performance boost

t

DEFERRING AND CONTROLLING STATE MUTATION

Algorithm runner

Mongo

Mongo Writer

Instructions

AN INTERPRETER

Page 42: From node.js to Scala - with a 100x performance boost

t

DEFERRING STATE MUTATION

id1 id2 id1 id1 id2 id2 id1 id2 id1 id1 id2 id2

Mongoget

set

OPTIMIZE ME!

Page 43: From node.js to Scala - with a 100x performance boost

t

FOLDING INSTRUCTIONS TO REDUCE I/O

id1 -> inst1 :: inst2 :: inst3 … :: Nil

id2 -> inst1 :: inst2 :: inst3 … :: Nil

Mongo

getMultiple setMultiple

foldLeft(initialObject)(processInstruction)

Page 44: From node.js to Scala - with a 100x performance boost

DECOUPLE STATE MUTATION FROM PROCESSING

OPTIMIZE STATE MUTATION WHEN INTERPRETING

KEY TAKEAWAYS

Page 45: From node.js to Scala - with a 100x performance boost

t

MEASURE!

Dropwizard Metrics + metrics-scala:

Page 46: From node.js to Scala - with a 100x performance boost

KEY TAKEAWAYS

INSTRUMENT AWAY!

Page 47: From node.js to Scala - with a 100x performance boost

t

FINAL NUMBERS AND BENEFITS

OVERALL RATE IMPROVMENT:

~ 16 events/s on a single node.js process at peak

1600-2500 events/s on a single pipeline at peak

ISOLATION

COMPLETE DETERMINISM

SCALABILITY

Actor-per-Customer; failure isolation

More nodes => more actors; reduced I/O

Actions determined entirely by Kafka contents;

amazing for debugging!

Page 48: From node.js to Scala - with a 100x performance boost

Q&A

Page 50: From node.js to Scala - with a 100x performance boost

t

GROCERY LIST

RabbitMQ - op-rabbit

MongoDB - reactivemongo

Kafka - kafka-clients

Zookeeper - curator

Dependency Injection - scaldi

Logging - log4j2, scala-logging, raven-log4j2

Metrics - Dropwizard Metrics, metrics-scala

Config - Typesafe Config

JSON - play-json

Binary serde - kryo/chill


Recommended