115
Real World Lessons on the Pain Points of Node.js Applications @Ben_Hall [email protected] OcelotUproar.com / Katacoda.com

Real World Lessons on the Pain Points of Node.JS Application

Embed Size (px)

Citation preview

Page 1: Real World Lessons on the Pain Points of Node.JS Application

Real World Lessons on the Pain Points of Node.js Applications

@[email protected] / Katacoda.com

Page 2: Real World Lessons on the Pain Points of Node.JS Application

@Ben_Hall / Blog.BenHall.me.ukOcelot Uproar

WH

O AM

I?

Page 3: Real World Lessons on the Pain Points of Node.JS Application

Learn via Interactive Browser-Based LabsKatacoda.com

Page 4: Real World Lessons on the Pain Points of Node.JS Application

Agenda

• Creating strong foundation– Node v6/v7, NPM, Security

• Error Handling• Async / Promises• Deploying / Scaling• Performance• Debugging

Page 5: Real World Lessons on the Pain Points of Node.JS Application

Provide an overview of our node.js experiences

and the tasks we wish we did earlier!

Page 6: Real World Lessons on the Pain Points of Node.JS Application

Strong Foundations

Page 7: Real World Lessons on the Pain Points of Node.JS Application

Upgrading from Node v0.10.38 to v6.1.0

Page 8: Real World Lessons on the Pain Points of Node.JS Application
Page 9: Real World Lessons on the Pain Points of Node.JS Application

#nodestats for March: Node 6.x hits 48% share, Node 7.x breaks 15%, 0.10 and 0.12 drop below 10% share for the first time:

https://mobile.twitter.com/i/web/status/838922927735132160

Page 10: Real World Lessons on the Pain Points of Node.JS Application

Previous Node Versioning

• Even === Stable– 0.10, 0.12, 4, 6

• Odd === Beta– 0.9, 0.11, 5

Page 11: Real World Lessons on the Pain Points of Node.JS Application
Page 12: Real World Lessons on the Pain Points of Node.JS Application

Node Release Stages

• CURRENT: new features (and bug fixes and security patches)

• ACTIVE LTS: bug fixes (and security patches)• MAINTENANCE: only security patches

Page 13: Real World Lessons on the Pain Points of Node.JS Application

Docker to test deployment

• Didn’t need to install anything on host

> docker run -it -v $(pwd):/src -p 3000 node:6 root@container:> npm install root@container:> npm start

Page 14: Real World Lessons on the Pain Points of Node.JS Application

Default to Underscore.js ?

Page 15: Real World Lessons on the Pain Points of Node.JS Application

Fixing NPM

Page 16: Real World Lessons on the Pain Points of Node.JS Application

Lock down NPM dependencies because no-one respects SemVer

Page 17: Real World Lessons on the Pain Points of Node.JS Application

AngularJs 1.2 => 1.3"dependencies": { "angular": "^1.2.16”}

Page 18: Real World Lessons on the Pain Points of Node.JS Application

Angular 1.2 => 1.3> angular.element(document)[#document]

> angular.element(document)TypeError: undefined is not a function

Page 19: Real World Lessons on the Pain Points of Node.JS Application

Lock Down Dependencies

Randomly breaking builds and deployments will occur otherwise

Page 20: Real World Lessons on the Pain Points of Node.JS Application

$ npm shrinkwrap

Lock down dependencies to what’s running locally

Page 21: Real World Lessons on the Pain Points of Node.JS Application
Page 22: Real World Lessons on the Pain Points of Node.JS Application

Hard code versions in package.json

"dependencies": { "angular": “1.2.23”}

Page 23: Real World Lessons on the Pain Points of Node.JS Application

$ npm outdated

Page 24: Real World Lessons on the Pain Points of Node.JS Application
Page 25: Real World Lessons on the Pain Points of Node.JS Application

.npmrc

• https://docs.npmjs.com/misc/config

> cat .npmrcsave=truesave-exact=true

Page 26: Real World Lessons on the Pain Points of Node.JS Application

npm install -g

Page 27: Real World Lessons on the Pain Points of Node.JS Application
Page 28: Real World Lessons on the Pain Points of Node.JS Application

Replaced Glup, Grunt with Make

Page 29: Real World Lessons on the Pain Points of Node.JS Application

templates:handlebars views/templates/*.hbs -f

public/js/templates.js

> make templates

Page 30: Real World Lessons on the Pain Points of Node.JS Application

Security

Page 31: Real World Lessons on the Pain Points of Node.JS Application

Child Process Execchild_process.exec(req.query.url, function (err, data) { console.log(data);});

https://localhost:49155/api/openUrlInDefaultBrowser?url=c:/windows/system32/calc.exe

Thanks TrendMicro Antivirus on Windows!

https://code.google.com/p/google-security-research/issues/detail?id=693

Page 32: Real World Lessons on the Pain Points of Node.JS Application

Cross-Site Request Forgeryvar csrf = require('csurf');

var csrfProtection = csrf({ cookie: true }); var parseForm = bodyParser.urlencoded({ extended: false });

app.get('/form', csrfProtection, function(req, res) { res.render('send', { csrfToken: req.csrfToken() });});

app.post('/process', parseForm, csrfProtection, function(req, res) { res.send('data is being processed');});

https://blog.risingstack.com/node-js-security-checklist/

Page 33: Real World Lessons on the Pain Points of Node.JS Application

Rate Limitingvar ratelimit = require('koa-ratelimit');

var ipBasedRatelimit = ratelimit({ db: redis.createClient(), duration: 60000, max: 10, id: function (context) { return context.ip; }});

app.post('/login', ipBasedRatelimit, handleLogin);

https://blog.risingstack.com/node-js-security-checklist/

Page 34: Real World Lessons on the Pain Points of Node.JS Application

Security Audit NPM Packages> npm install nsp> nsp check(+) 18 vulnerabilities found

Page 35: Real World Lessons on the Pain Points of Node.JS Application

https://nodesecurity.io/

• Root Path Disclosure (2x)• Regular Expression Denial of Service (10x)• Incorrect Handling of Non-Boolean

Comparisons During Minification• Denial-of-Service Extended Event Loop Blocking• Denial-of-Service Memory Exhaustion• Symlink Arbitrary File Overwrite• Remote Memory Disclosure (2x)

Page 37: Real World Lessons on the Pain Points of Node.JS Application
Page 38: Real World Lessons on the Pain Points of Node.JS Application
Page 39: Real World Lessons on the Pain Points of Node.JS Application
Page 40: Real World Lessons on the Pain Points of Node.JS Application

https://blog.acolyer.org/2017/03/07/thou-shalt-not-depend-on-me-analysing-the-use-of-outdated-javascript-libraries-on-the-web/

Page 41: Real World Lessons on the Pain Points of Node.JS Application

Create Strong Foundations

Page 42: Real World Lessons on the Pain Points of Node.JS Application

Error Handling

Page 43: Real World Lessons on the Pain Points of Node.JS Application

Wasn’t great from the start

Page 44: Real World Lessons on the Pain Points of Node.JS Application

Try {} Catch {}

Page 45: Real World Lessons on the Pain Points of Node.JS Application

Try {} Catch {}

Page 46: Real World Lessons on the Pain Points of Node.JS Application
Page 47: Real World Lessons on the Pain Points of Node.JS Application

Domains haven’t really worked

Page 48: Real World Lessons on the Pain Points of Node.JS Application

https://raw.githubusercontent.com/strongloop/zone/master/showcase/curl/curl-zone.js

Zones? No. Not really

Page 49: Real World Lessons on the Pain Points of Node.JS Application

Returning String as Error

Page 50: Real World Lessons on the Pain Points of Node.JS Application

Strongly typed errors

Page 51: Real World Lessons on the Pain Points of Node.JS Application
Page 52: Real World Lessons on the Pain Points of Node.JS Application

Async Flow Control

Page 53: Real World Lessons on the Pain Points of Node.JS Application
Page 54: Real World Lessons on the Pain Points of Node.JS Application

Promises

Promises… Promises… Never break your promises.

Personally, I never make promises.

Page 55: Real World Lessons on the Pain Points of Node.JS Application

http://domenic.me/2012/10/14/youre-missing-the-point-of-promises/

Page 56: Real World Lessons on the Pain Points of Node.JS Application

Callbacks

So good it’s got it’s own website callbackhell.com

Page 57: Real World Lessons on the Pain Points of Node.JS Application

“The goal isn’t about removing levels of indentation but rather writing modular code that

is easy to reason about”

Strongloop Blog

http://strongloop.com/strongblog/node-js-callback-hell-promises-generators/

Page 58: Real World Lessons on the Pain Points of Node.JS Application
Page 59: Real World Lessons on the Pain Points of Node.JS Application
Page 60: Real World Lessons on the Pain Points of Node.JS Application
Page 61: Real World Lessons on the Pain Points of Node.JS Application
Page 62: Real World Lessons on the Pain Points of Node.JS Application
Page 63: Real World Lessons on the Pain Points of Node.JS Application
Page 64: Real World Lessons on the Pain Points of Node.JS Application
Page 65: Real World Lessons on the Pain Points of Node.JS Application

Loops + Async Callbacks

Page 66: Real World Lessons on the Pain Points of Node.JS Application

Loops + Async Callbacks

Page 67: Real World Lessons on the Pain Points of Node.JS Application

“You can't get into callback hell if you don't go there.”

Isaac Schlueter

Page 68: Real World Lessons on the Pain Points of Node.JS Application

Node 7 – Async Awaitclass Demo { async greeting() { const h = await this.world(); return h; } world() { return Promise.resolve('hello world'); }}

const retval = await demo.greeting();

Page 69: Real World Lessons on the Pain Points of Node.JS Application

Node 7 – Async Await Errorsasync getPersonFullNameWithTryCatch() { try { let response = await fetch('./data/person2.json'); } catch(e) { console.log('there was an error'); console.log(e); }}

Page 70: Real World Lessons on the Pain Points of Node.JS Application

DEPLOY!

Page 71: Real World Lessons on the Pain Points of Node.JS Application

Single Threaded

Page 72: Real World Lessons on the Pain Points of Node.JS Application

CPU Intensive?

Array Filtering / Sorting / Processing

Page 73: Real World Lessons on the Pain Points of Node.JS Application
Page 74: Real World Lessons on the Pain Points of Node.JS Application

Maybe not use Node?

Golang has a great community

Where Node was a few years ago?

Page 75: Real World Lessons on the Pain Points of Node.JS Application

Have more threads

Page 76: Real World Lessons on the Pain Points of Node.JS Application

Solved Problem?

Page 77: Real World Lessons on the Pain Points of Node.JS Application

var cluster = require('cluster');var http = require('http');var numCPUs = require('os').cpus().length;

if (cluster.isMaster) { // Fork workers. for (var i = 0; i < numCPUs; i++) { cluster.fork(); }

cluster.on('exit', function(worker, code, signal) { console.log('worker ' + worker.process.pid + ' died'); });} else { // Workers can share any TCP connection // In this case it is an HTTP server http.createServer(function(req, res) { res.writeHead(200); res.end("hello world\n"); }).listen(8000);}

Page 78: Real World Lessons on the Pain Points of Node.JS Application

> NODE_DEBUG=cluster node server.js23521,Master Worker 23524 online23521,Master Worker 23526 online23521,Master Worker 23523 online23521,Master Worker 23528 online

Page 79: Real World Lessons on the Pain Points of Node.JS Application
Page 80: Real World Lessons on the Pain Points of Node.JS Application
Page 81: Real World Lessons on the Pain Points of Node.JS Application
Page 82: Real World Lessons on the Pain Points of Node.JS Application

Deploying with Docker

Page 83: Real World Lessons on the Pain Points of Node.JS Application
Page 84: Real World Lessons on the Pain Points of Node.JS Application

Container

https://www.docker.com/whatisdocker/

Container

Page 85: Real World Lessons on the Pain Points of Node.JS Application

Deploying Node App via Docker> cat DockerfileFROM node:6-onbuildEXPOSE 3000

> docker build –t my-node-app .> docker run –p 3000:3000 my-node-app

Page 86: Real World Lessons on the Pain Points of Node.JS Application

59,040 environments/day/server

Page 87: Real World Lessons on the Pain Points of Node.JS Application
Page 88: Real World Lessons on the Pain Points of Node.JS Application

112,320 environments/day/server

Page 89: Real World Lessons on the Pain Points of Node.JS Application

> docker run -d \ -p 80:80 \ -v /var/run/docker.sock:/tmp/docker.sock:ro \ jwilder/nginx-proxy

> docker run --name web \ -e VIRTUAL_HOST=www.katacoda.com my-node-app

Page 90: Real World Lessons on the Pain Points of Node.JS Application

Load Balancer

Nginx Proxy

Node Node

Node Node

Node Node

Nginx Proxy

Node Node

Node Node

Node Node

Nginx Proxy

Node Node

Node Node

Node Node

Page 91: Real World Lessons on the Pain Points of Node.JS Application

Health Endpointsrouter.get('/_specialfunctions/_check', function(req, res) { async.parallel([ check_docker, check_starter, check_redis, check_pg ], function(err, results) { if(err) { console.log("Health check failed", err); res.status(500); return res.json({healthy: false, details: err}); }

res.json({healthy: true}); })});

Page 92: Real World Lessons on the Pain Points of Node.JS Application

var check_docker = function(cb) { docker.ping(function(err) { handle_error('docker', err, cb);});};

var check_redis = function(cb) { redis.status(function(err, connected) { if(err === null && connected === "ready") { cb(); } else { handle_error('redis', {msg: 'Not Connected', err: err}, cb); } })};

var check_pg = function(cb) { pg.status(function(err) { handle_error('postgres', err, cb);});};

Page 93: Real World Lessons on the Pain Points of Node.JS Application

Careful!

socket.io and global state

Page 94: Real World Lessons on the Pain Points of Node.JS Application

Sticky Sessions

Compiled Nginx + OSS Modules

Page 95: Real World Lessons on the Pain Points of Node.JS Application

Global State as a Service

Microservices FTW!!

Page 96: Real World Lessons on the Pain Points of Node.JS Application

Code Performance Still Matters

Page 97: Real World Lessons on the Pain Points of Node.JS Application

Performance

Page 98: Real World Lessons on the Pain Points of Node.JS Application

> npm install v8-profiler const profiler = require('v8-profiler')const fs = require('fs')var profilerRunning = false

function toggleProfiling () { if (profilerRunning) { const profile = profiler.stopProfiling() console.log('stopped profiling') profile.export() .pipe(fs.createWriteStream('./myapp-'+Date.now()+'.cpuprofile')) .once('error', profiler.deleteAllProfiles) .once('finish', profiler.deleteAllProfiles) profilerRunning = false return } profiler.startProfiling() profilerRunning = true console.log('started profiling')}

process.on('SIGUSR2', toggleProfiling)

> kill -SIGUSR2 <pid>

Page 99: Real World Lessons on the Pain Points of Node.JS Application
Page 100: Real World Lessons on the Pain Points of Node.JS Application

JetBrains WebStorm

Page 101: Real World Lessons on the Pain Points of Node.JS Application

OpenTracing - Zipkin

Page 102: Real World Lessons on the Pain Points of Node.JS Application
Page 103: Real World Lessons on the Pain Points of Node.JS Application
Page 104: Real World Lessons on the Pain Points of Node.JS Application

Prometheus + Grafana

Page 105: Real World Lessons on the Pain Points of Node.JS Application
Page 106: Real World Lessons on the Pain Points of Node.JS Application

Debugging

Page 107: Real World Lessons on the Pain Points of Node.JS Application

require(‘debug’);

Page 108: Real World Lessons on the Pain Points of Node.JS Application

Webstorm

Page 109: Real World Lessons on the Pain Points of Node.JS Application

VS Code

Page 110: Real World Lessons on the Pain Points of Node.JS Application

Profiling Node Applications

March 10, 2017 @ 09:00 Fontaine E

Page 111: Real World Lessons on the Pain Points of Node.JS Application

Real-Time Monitoring with Grafana, StatsD and InfluxDB

March 10, 2017 @ 15:00

Page 112: Real World Lessons on the Pain Points of Node.JS Application

Testing?!

Page 113: Real World Lessons on the Pain Points of Node.JS Application
Page 114: Real World Lessons on the Pain Points of Node.JS Application

Summary

• Upgrade to Node.js v6• Start looking at ES6 / Node 7• Security• Manage your errors• Forgot making promises• Scale using Docker

Page 115: Real World Lessons on the Pain Points of Node.JS Application

Thank you!@Ben_Hall

[email protected]