183
PEDROFRANCESCHI @pedroh96 [email protected] github.com/pedrofranceschi Node.js no

Node.js no Pagar.me

Embed Size (px)

Citation preview

Page 1: Node.js no Pagar.me

PEDROFRANCESCHI @pedroh96

[email protected] github.com/pedrofranceschi

Node.js no

Page 2: Node.js no Pagar.me

Assuntos

Page 3: Node.js no Pagar.me

• O problema

Assuntos

Page 4: Node.js no Pagar.me

• O problema

• Por que Node.js?

Assuntos

Page 5: Node.js no Pagar.me

• O problema

• Por que Node.js?

• Problemas de Node.js

Assuntos

Page 6: Node.js no Pagar.me

• O problema

• Por que Node.js?

• Problemas de Node.js

• Node.js “the right way”

Assuntos

Page 7: Node.js no Pagar.me

• O problema

• Por que Node.js?

• Problemas de Node.js

• Node.js “the right way”

• Repensando a infraestrutura (+ Microservices)

Assuntos

Page 8: Node.js no Pagar.me

• O problema

• Por que Node.js?

• Problemas de Node.js

• Node.js “the right way”

• Repensando a infraestrutura (+ Microservices)

• Deployment (+ Continuous Integration)

Assuntos

Page 9: Node.js no Pagar.me

• O problema

• Por que Node.js?

• Problemas de Node.js

• Node.js “the right way”

• Repensando a infraestrutura (+ Microservices)

• Deployment (+ Continuous Integration)

• Conclusões…

Assuntos

Page 10: Node.js no Pagar.me

O problema

Page 11: Node.js no Pagar.me

“Montar um gateway de pagamentos amigável para desenvolvedores e

empreendedores”

Page 12: Node.js no Pagar.me

“A forma mais simples de receber pagamentos online”

Page 13: Node.js no Pagar.me

API RESTful

Dashboard Angular.js

RubyNode.js

Python Java

.NET

PHPC#

Page 14: Node.js no Pagar.me

Premissas da API

Page 15: Node.js no Pagar.me

• Simplicidade: RESTful + JSON

Premissas da API

Page 16: Node.js no Pagar.me

• Simplicidade: RESTful + JSON

• Ambiente de testes isolado e decente

Premissas da API

Page 17: Node.js no Pagar.me

• Simplicidade: RESTful + JSON

• Ambiente de testes isolado e decente

• Segurança sem comprometer simplicidade (PCI)

Premissas da API

Page 18: Node.js no Pagar.me

• Simplicidade: RESTful + JSON

• Ambiente de testes isolado e decente

• Segurança sem comprometer simplicidade (PCI)

• Uptime de 99,9%

Premissas da API

Page 19: Node.js no Pagar.me

• Simplicidade: RESTful + JSON

• Ambiente de testes isolado e decente

• Segurança sem comprometer simplicidade (PCI)

• Uptime de 99,9%

• Escalabilidade

Premissas da API

Page 20: Node.js no Pagar.me

Por que Node.js?

Page 21: Node.js no Pagar.me

Por que Node.js?

Request de transação

API RESTful

Sistema antifraude

fraude

legítimaAdquirente (Cielo, Rede, etc)

sucesso/erro

erro

Page 22: Node.js no Pagar.me

Por que Node.js?

Request de transação

API RESTful

Sistema antifraude

fraude

legítimaAdquirente (Cielo, Rede, etc)

10.000 ms

3.000

ms

sucesso/erro

erro

Page 23: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

Page 24: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

• Requests externos demorados (>1.000ms)

Page 25: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

• Requests externos demorados (>1.000ms)

• I/O intenso em banco de dados

Page 26: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

• Requests externos demorados (>1.000ms)

• I/O intenso em banco de dados

• Totalmente assíncrono, single thread e event-based

Page 27: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

• Requests externos demorados (>1.000ms)

• I/O intenso em banco de dados

• Totalmente assíncrono, single thread e event-based

• Alta carga na aplicação

Page 28: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

• Requests externos demorados (>1.000ms)

• I/O intenso em banco de dados

• Totalmente assíncrono, single thread e event-based

• Alta carga na aplicação

• Pouco processamento (sem blocking de CPU)

Page 29: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

“Mas é só usar threads em qualquer linguagem!..”

Page 30: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

“Mas é só usar threads em qualquer linguagem!..”

Não.

Page 31: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1.000 threads por segundo

Page 32: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1.000 threads por segundo

… se cada request leva em média 10 segundos …

Page 33: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1.000 threads por segundo

… se cada request leva em média 10 segundos …

Em 9 segundos, teremos 9.000 threads

Page 34: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1.000 threads por segundo

… se cada request leva em média 10 segundos …

Em 9 segundos, teremos 9.000 threads

Isso escala? :P :P :P

Page 35: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

Agora, em Node.js…

Page 36: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1 thread

Page 37: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1 thread

… se cada request leva em média 10 segundos …

Page 38: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1 thread

… se cada request leva em média 10 segundos …

Em 9 segundos, teremos 1 thread

Page 39: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1 thread

… se cada request leva em média 10 segundos …

Em 9 segundos, teremos 1 thread

Isso escala? Sim.

Page 40: Node.js no Pagar.me

Por que Node.js? (no nosso caso)

1.000 requests por segundo com conexão a uma API externa + I/O no DB = 1 thread

… se cada request leva em média 10 segundos …

Em 9 segundos, teremos 1 thread

Isso escala? Sim.#eventloopFTW

Page 41: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

Page 42: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

I/O

Page 43: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

I/O

Page 44: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

I/O

I/O bloqueante (aplicação travada)

Page 45: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

I/O

I/O bloqueante (aplicação travada)

Page 46: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

I/Oretorno

I/O bloqueante (aplicação travada)

Page 47: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

I/Oretorno

I/O bloqueante (aplicação travada)

I/Oretorno

I/O bloqueante (aplicação travada)

Page 48: Node.js no Pagar.me

I/O síncrona

Aplicação

Sistema operacional

I/Oretorno

I/O bloqueante (aplicação travada)

I/Oretorno

I/O bloqueante (aplicação travada)

I/Oretorno

I/O bloqueante (aplicação travada)

Page 49: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

Page 50: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Page 51: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Page 52: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

Page 53: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

Page 54: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

I/O bloqueante (thread travada)

Page 55: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

I/O bloqueante (thread travada)

Page 56: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

I/O bloqueante (thread travada)

Page 57: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

callback

I/O bloqueante (thread travada)

Page 58: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

callback

I/O bloqueante (thread travada)

I/O

Thread

callback

I/O bloqueante (thread travada)

Page 59: Node.js no Pagar.me

I/O “assíncrona” com threads

Aplicação

Sistema operacional

I/O

Thread

callback

I/O bloqueante (thread travada)

I/O

Thread

callback

I/O bloqueante (thread travada)

I/O

Thread

callback

I/O bloqueante (thread travada)

Page 60: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional

Page 61: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional

I/O

Page 62: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional

I/O

Page 63: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional

I/O

Page 64: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional

I/O

Page 65: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

I/O

Page 66: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

I/O

Page 67: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

I/O

Page 68: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

I/O

Page 69: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

I/O

Page 70: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

I/Ocallback

Page 71: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

I/Ocallback

I/O

Page 72: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

……………………………………

I/Ocallback

I/O

Page 73: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

……………………………………

I/Ocallback

I/OI/O

Page 74: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

…………………………………………………………………………

I/Ocallback

I/OI/O

Page 75: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

…………………………………………………………………………

I/Ocallback

I/OI/O

callback

Page 76: Node.js no Pagar.me

O segredo do Node.js

JavaScript (event loop)

V8

libuv

Sistema operacional……………………………………

operações assíncronas em nível de OS

…………………………………………………………………………

I/Ocallback

I/OI/O

callbackcallback

Page 77: Node.js no Pagar.me

Node.js escala em I/O bloqueante, não em utilização de CPU

(threads são boas em processamento paralelo)

Page 78: Node.js no Pagar.me
Page 79: Node.js no Pagar.me
Page 80: Node.js no Pagar.me

Problemas de Node.js

Page 81: Node.js no Pagar.me

Código assíncrono (race conditions, callback hell, testes assíncronos, etc)

db.query("SELECT a FROM users WHERE ...;", function (err, result1) { db.query("SELECT b FROM users WHERE ...;", function (err, result2) { db.query("SELECT c FROM users WHERE ...;", function (err, result3) { db.query("SELECT d FROM users WHERE ...;", function (err, result4) { db.query("SELECT e FROM users WHERE ...;", function (err, result5) { console.log("Finished."); }); }); }); }); });

Um ótimo exemplo do que não fazer: callback hell.

Problemas de Node.js

Page 82: Node.js no Pagar.me

Problemas de Javascript: bizarrices e facilidade em não seguir padrões e orientação a objetos.

> 0.1+0.2 0.30000000000000004

> typeof NaN 'number'

> NaN === NaN false

Cortesia do wtfjs.com

Problemas de Node.js

Page 83: Node.js no Pagar.me

Exceptions não tratadas matam o processo.var name = “Pedro Franceschi";

console.log("Tamanho do primeiro nome: " + name.split(" ")[0].length); console.log("Tamanho do segundo nome: " + name.split(" ")[1].length);

Problemas de Node.js

$ node test.js Tamanho do primeiro nome: 5 Tamanho do segundo nome: 10

Page 84: Node.js no Pagar.me

Exceptions não tratadas matam o processo.var name = “Pedro";

console.log("Tamanho do primeiro nome: " + name.split(" ")[0].length); console.log("Tamanho do segundo nome: " + name.split(" ")[1].length);

Problemas de Node.js

$ node test.js Tamanho do primeiro nome: 5

/private/tmp/test.js:4 console.log("Tamanho do segundo nome: " + name.split(" ")[1].length); ^ TypeError: Cannot read property 'length' of undefined at Object.<anonymous> (/private/tmp/test.js:4:61) at Module._compile (module.js:456:26) at Object.Module._extensions..js (module.js:474:10) at Module.load (module.js:356:32) at Function.Module._load (module.js:312:12) at Function.Module.runMain (module.js:497:10) at startup (node.js:119:16) at node.js:901:3

Page 85: Node.js no Pagar.me

Problemas de Node.js

Page 86: Node.js no Pagar.me

Problemas de Node.js

• Single thread (escalar horizontalmente e verticalmente com múltiplas instâncias)

Page 87: Node.js no Pagar.me

Problemas de Node.js

• Single thread (escalar horizontalmente e verticalmente com múltiplas instâncias)

• Leaks de memória difíceis de detectar (back-end em C++, variáveis globalizadas, closures, etc)

Page 88: Node.js no Pagar.me

Problemas de Node.js

• Single thread (escalar horizontalmente e verticalmente com múltiplas instâncias)

• Leaks de memória difíceis de detectar (back-end em C++, variáveis globalizadas, closures, etc)

• Programadores front-end mexendo em back-end (“é tudo Javascript!!”)

Page 89: Node.js no Pagar.me

Problemas de Node.js

• Single thread (escalar horizontalmente e verticalmente com múltiplas instâncias)

• Leaks de memória difíceis de detectar (back-end em C++, variáveis globalizadas, closures, etc)

• Programadores front-end mexendo em back-end (“é tudo Javascript!!”)

• Existe a 6 anos, porém ainda é beta (v0.12.0) - e às vezes você precisa usar unstable em produção

Page 90: Node.js no Pagar.me
Page 91: Node.js no Pagar.me

Node.js “the right way”

Page 92: Node.js no Pagar.me
Page 93: Node.js no Pagar.me

Qualidade de vida vs. tempo usando Node

Page 94: Node.js no Pagar.me

Qualidade de vida vs. tempo usando Node

Node é muito legal!!!

Page 95: Node.js no Pagar.me

Qualidade de vida vs. tempo usando Node

Node é muito legal!!! Ops… Meu código está

ficando uma zona…

Page 96: Node.js no Pagar.me

Qualidade de vida vs. tempo usando Node

Node é muito legal!!! Ops… Meu código está

ficando uma zona…

Queria ter feito em Rails…

Page 97: Node.js no Pagar.me

Qualidade de vida vs. tempo usando Node

Node é muito legal!!! Ops… Meu código está

ficando uma zona…

Queria ter feito em Rails…

MVC de verdade + Promise + Bluebird <3

Page 98: Node.js no Pagar.me

Modules

Node.js “the right way”

var PI = Math.PI;

exports.area = function (r) { return PI * r * r; };

exports.circumference = function (r) { return 2 * PI * r; };

circle.js

var circle = require('./circle.js');

console.log( 'The area of a circle of radius 4 is ' + circle.area(4));

main.js

Page 99: Node.js no Pagar.me

Node.js “the right way”

describe('Array', function(){ describe('#indexOf()', function(){ it('should return -1 when the value is not present', function(){ [1,2,3].indexOf(5).should.equal(-1); }) })

describe(‘#indexOf() after one second', function(){ before(function(done){ setTimeout(function(){ done(); }, 1000); });

it('should return -1 when the value is not present', function(){ [1,2,3].indexOf(5).should.equal(-1); }) }) });

Testes (JavaScript quebra) (https://github.com/visionmedia/mocha e https://github.com/visionmedia/should.js/)

Page 100: Node.js no Pagar.me

Node.js “the right way”Models (Sequelize/Mongoose)

var Transaction = Sequelize.define('Transaction', { amount: Sequelize.INTEGER, cost: Sequelize.FLOAT, status: { type: Sequelize.ENUM, values: ['paid', 'refused', 'refunded'], defaultValue: 'processing' } }, { instanceMethods: { calculateCost: function(status){ status = status || this.status; if(status == 'paid') { return 50 + (this.amount * 0.015); } }, }, classMethods: { }, hooks: { beforeUpdate: function(transaction) { return transaction.calculateCost() .then(function(cost) { transaction.cost = cost; }); } }, });

Page 101: Node.js no Pagar.me

Node.js “the right way”Models (Sequelize/Mongoose)

var Transaction = Sequelize.define('Transaction', { amount: Sequelize.INTEGER, cost: Sequelize.FLOAT, status: { type: Sequelize.ENUM, values: ['paid', 'refused', 'refunded'], defaultValue: 'processing' } }, { instanceMethods: { calculateCost: function(status){ status = status || this.status; if(status == 'paid') { return 50 + (this.amount * 0.015); } }, }, classMethods: { }, hooks: { beforeUpdate: function(transaction) { return transaction.calculateCost() .then(function(cost) { transaction.cost = cost; }); } }, });

Page 102: Node.js no Pagar.me

Node.js “the right way”Models (Sequelize/Mongoose)

var Transaction = Sequelize.define('Transaction', { amount: Sequelize.INTEGER, cost: Sequelize.FLOAT, status: { type: Sequelize.ENUM, values: ['paid', 'refused', 'refunded'], defaultValue: 'processing' } }, { instanceMethods: { calculateCost: function(status){ status = status || this.status; if(status == 'paid') { return 50 + (this.amount * 0.015); } }, }, classMethods: { }, hooks: { beforeUpdate: function(transaction) { return transaction.calculateCost() .then(function(cost) { transaction.cost = cost; }); } }, });

Page 103: Node.js no Pagar.me

Node.js “the right way”Models (Sequelize/Mongoose)

var Transaction = Sequelize.define('Transaction', { amount: Sequelize.INTEGER, cost: Sequelize.FLOAT, status: { type: Sequelize.ENUM, values: ['paid', 'refused', 'refunded'], defaultValue: 'processing' } }, { instanceMethods: { calculateCost: function(status){ status = status || this.status; if(status == 'paid') { return 50 + (this.amount * 0.015); } }, }, classMethods: { }, hooks: { beforeUpdate: function(transaction) { return transaction.calculateCost() .then(function(cost) { transaction.cost = cost; }); } }, });

Page 104: Node.js no Pagar.me

Node.js “the right way”Models (Sequelize/Mongoose)

var Transaction = Sequelize.define('Transaction', { amount: Sequelize.INTEGER, cost: Sequelize.FLOAT, status: { type: Sequelize.ENUM, values: ['paid', 'refused', 'refunded'], defaultValue: 'processing' } }, { instanceMethods: { calculateCost: function(status){ status = status || this.status; if(status == 'paid') { return 50 + (this.amount * 0.015); } }, }, classMethods: { }, hooks: { beforeUpdate: function(transaction) { return transaction.calculateCost() .then(function(cost) { transaction.cost = cost; }); } }, });

Page 105: Node.js no Pagar.me

Node.js “the right way”Promises (Bluebird)

fs.readFile("file.json", function(err, val) { if(err) { console.error("unable to read file"); } else { try { val = JSON.parse(val); console.log(val.success); } catch(e) { console.error("invalid json in file"); } } });

Page 106: Node.js no Pagar.me

Node.js “the right way”Promises (Bluebird)

fs.readFile("file.json", function(err, val) { if(err) { console.error("unable to read file"); } else { try { val = JSON.parse(val); console.log(val.success); } catch(e) { console.error("invalid json in file"); } } });

Page 107: Node.js no Pagar.me

Node.js “the right way”Promises (Bluebird)

fs.readFileAsync("file.json").then(JSON.parse).then(function(val) { console.log(val.success); }) .catch(SyntaxError, function(e) { console.error("invalid json in file"); }) .catch(function(e){ console.error("unable to read file") });

Assim é bem melhor :)

Page 108: Node.js no Pagar.me

Node.js “the right way”Lodash

var lines = [ ['name', 'type', 'cost'], ['iPhone', 'cellphone', '2000'], ['MacBook', 'computer', '10000'], ['iPad', 'tablet', '1500'] ];

var joinedLines = [];

for(var i = 0; i < lines.length; i++) { joinedLines.push(lines[i].join(',')); }

var csvContent = joinedLines.join('\n');

name,type,cost iPhone,cellphone,2000 MacBook,computer,10000 iPad,tablet,1500

Output

Page 109: Node.js no Pagar.me

Node.js “the right way”Lodash

var lines = [ ['name', 'type', 'cost'], ['iPhone', 'cellphone', '2000'], ['MacBook', 'computer', '10000'], ['iPad', 'tablet', '1500'] ];

var joinedLines = [];

for(var i = 0; i < lines.length; i++) { joinedLines.push(lines[i].join(',')); }

var csvContent = joinedLines.join('\n');

name,type,cost iPhone,cellphone,2000 MacBook,computer,10000 iPad,tablet,1500

Output

Page 110: Node.js no Pagar.me

Node.js “the right way”Lodash

var lines = [ ['name', 'type', 'cost'], ['iPhone', 'cellphone', '2000'], ['MacBook', 'computer', '10000'], ['iPad', 'tablet', '1500'] ];

var joinedLines = [];

for(var i = 0; i < lines.length; i++) { joinedLines.push(lines[i].join(',')); }

var csvContent = joinedLines.join('\n');

name,type,cost iPhone,cellphone,2000 MacBook,computer,10000 iPad,tablet,1500

Output

Page 111: Node.js no Pagar.me

Node.js “the right way”

Assim é bem melhor :)

Lodash

var _ = require('lodash');

var lines = [ ['name', 'type', 'cost'], ['iPhone', 'cellphone', '2000'], ['MacBook', 'computer', '10000'], ['iPad', 'tablet', '1500'] ];

var csvContent = _.map(lines, function(line){ return line.join(','); }).join('\n');

name,type,cost iPhone,cellphone,2000 MacBook,computer,10000 iPad,tablet,1500

Output

Page 112: Node.js no Pagar.me

Node.js “the right way”

Page 113: Node.js no Pagar.me

Node.js “the right way”

• Seguir e manter um code style (dica: Google JavaScript Style Guide)

Page 114: Node.js no Pagar.me

Node.js “the right way”

• Seguir e manter um code style (dica: Google JavaScript Style Guide)

• Tratamento de erros consistente via Promise (evitar que processos morram)

Page 115: Node.js no Pagar.me

Node.js “the right way”

• Seguir e manter um code style (dica: Google JavaScript Style Guide)

• Tratamento de erros consistente via Promise (evitar que processos morram)

• Manter consistência entre as bibliotecas de Promise (i.e. usar a mesma do wrapper do database)

Page 116: Node.js no Pagar.me

Node.js “the right way”

• Seguir e manter um code style (dica: Google JavaScript Style Guide)

• Tratamento de erros consistente via Promise (evitar que processos morram)

• Manter consistência entre as bibliotecas de Promise (i.e. usar a mesma do wrapper do database)

• Sem for(var i = 0; i < object.length; i++) - #lodashFTW

Page 117: Node.js no Pagar.me

Node.js “the right way” utils

Page 118: Node.js no Pagar.me

Node.js “the right way” utils

• Express.js: lightweight HTTP framework

Page 119: Node.js no Pagar.me

Node.js “the right way” utils

• Express.js: lightweight HTTP framework

• Sequelize: ORM de MySQL, PostgreSQL, sqlite3, etc.

Page 120: Node.js no Pagar.me

Node.js “the right way” utils

• Express.js: lightweight HTTP framework

• Sequelize: ORM de MySQL, PostgreSQL, sqlite3, etc.

• Mongoose: ORM de MongoDB

Page 121: Node.js no Pagar.me

Node.js “the right way” utils

• Express.js: lightweight HTTP framework

• Sequelize: ORM de MySQL, PostgreSQL, sqlite3, etc.

• Mongoose: ORM de MongoDB

• Commander: wrapper de command line

Page 122: Node.js no Pagar.me

Node.js “the right way” utils

• Express.js: lightweight HTTP framework

• Sequelize: ORM de MySQL, PostgreSQL, sqlite3, etc.

• Mongoose: ORM de MongoDB

• Commander: wrapper de command line

• Vim: melhor editor de texto :P

Page 123: Node.js no Pagar.me

Repensando a infraestrutura

Page 124: Node.js no Pagar.me

Infraestrutura do Pagar.me

Router

api.pagar.me

Servidor da API (Node.js)

Ambiente de testes (sandbox dos clientes)

Ambiente de produção

Servidor da API (Node.js)

Page 125: Node.js no Pagar.me

Infraestrutura do Pagar.me

Router

api.pagar.me

Servidor da API (Node.js)

ElasticSearchElasticSearch

Ambiente de testes (sandbox dos clientes)

Ambiente de produção

Servidor da API (Node.js)

Page 126: Node.js no Pagar.me

Infraestrutura do Pagar.me

Router

api.pagar.me

Servidor da API (Node.js)

ElasticSearchElasticSearch

MySQL (transações e dados relacionais)

MySQL (transações e dados relacionais)

Ambiente de testes (sandbox dos clientes)

Ambiente de produção

Servidor da API (Node.js)

Page 127: Node.js no Pagar.me

Infraestrutura do Pagar.me

Router

api.pagar.me

Servidor da API (Node.js)

ElasticSearchElasticSearch

MySQL (transações e dados relacionais)

MySQL (transações e dados relacionais)

Ambiente de testes (sandbox dos clientes)

Ambiente de produção

Servidor da API (Node.js)

Redis +

Redis +

Page 128: Node.js no Pagar.me

Infraestrutura do Pagar.me

Router

api.pagar.me

Servidor da API (Node.js)

ElasticSearchElasticSearch

MySQL (transações e dados relacionais)

MySQL (transações e dados relacionais)

MongoDB (dados de clientes e não relacionais)

Ambiente de testes (sandbox dos clientes)

Ambiente de produção

Servidor da API (Node.js)

Redis +

Redis +

Page 129: Node.js no Pagar.me

Por que tantos bancos?

Page 130: Node.js no Pagar.me

Por que tantos bancos?• Separar dados de teste (sandbox dos clientes) dos dados de

produção

Page 131: Node.js no Pagar.me

Por que tantos bancos?• Separar dados de teste (sandbox dos clientes) dos dados de

produção

• MySQL: dados relacionais (transações, assinaturas, planos, cartões, etc.)

Page 132: Node.js no Pagar.me

Por que tantos bancos?• Separar dados de teste (sandbox dos clientes) dos dados de

produção

• MySQL: dados relacionais (transações, assinaturas, planos, cartões, etc.)

• MongoDB: dados não-relacionais (informações do cliente, usuários de uma conta, etc.)

Page 133: Node.js no Pagar.me

Por que tantos bancos?• Separar dados de teste (sandbox dos clientes) dos dados de

produção

• MySQL: dados relacionais (transações, assinaturas, planos, cartões, etc.)

• MongoDB: dados não-relacionais (informações do cliente, usuários de uma conta, etc.)

• ElasticSearch: indexação/buscas ultra-rápidas (expondo uma engine de buscas poderosa para os clientes)

Page 134: Node.js no Pagar.me

Por que tantos bancos?• Separar dados de teste (sandbox dos clientes) dos dados de

produção

• MySQL: dados relacionais (transações, assinaturas, planos, cartões, etc.)

• MongoDB: dados não-relacionais (informações do cliente, usuários de uma conta, etc.)

• ElasticSearch: indexação/buscas ultra-rápidas (expondo uma engine de buscas poderosa para os clientes)

• Redis: fila para notificações entre serviços

Page 135: Node.js no Pagar.me

Por que tantos bancos?• Separar dados de teste (sandbox dos clientes) dos dados de

produção

• MySQL: dados relacionais (transações, assinaturas, planos, cartões, etc.)

• MongoDB: dados não-relacionais (informações do cliente, usuários de uma conta, etc.)

• ElasticSearch: indexação/buscas ultra-rápidas (expondo uma engine de buscas poderosa para os clientes)

• Redis: fila para notificações entre serviços

• Não há porque se prender a uma tecnologia quando cada uma delas resolve uma parte do seu problema

Page 136: Node.js no Pagar.me

Infraestrutura do Pagar.me

Router

api.pagar.me

Servidor da API (Node.js)

ElasticSearchElasticSearch

MySQL (transações e dados relacionais)

MySQL (transações e dados relacionais)

MongoDB (dados de clientes e não relacionais)

Ambiente de testes (sandbox dos clientes)

Ambiente de produção

Servidor da API (Node.js)

Redis +

Redis +

Page 137: Node.js no Pagar.me

Infraestrutura do Pagar.me

Router

api.pagar.me

Servidor da API (Node.js)

ElasticSearchElasticSearch

MySQL (transações e dados relacionais)

MySQL (transações e dados relacionais)

MongoDB (dados de clientes e não relacionais)

Ambiente de testes (sandbox dos clientes)

Ambiente de produção

Servidor da API (Node.js)

Redis +

Redis +

Page 138: Node.js no Pagar.me

Microservices

Page 139: Node.js no Pagar.me
Page 140: Node.js no Pagar.me

Cliente

Page 141: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

Page 142: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

API RESTful (pagar.me/docs)

Page 143: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

API RESTful (pagar.me/docs)

API RESTful (serviço interno)

Page 144: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

API RESTful (pagar.me/docs)

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P

API RESTful (serviço interno)

Page 145: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

API RESTful (pagar.me/docs)

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P

~ 550 ms API RESTful (serviço interno)

Page 146: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

API RESTful (pagar.me/docs)~ 500ms

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P

~ 550 ms API RESTful (serviço interno)

Page 147: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

API RESTful (pagar.me/docs)~ 500ms

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P> 5000 ms

~ 550 ms API RESTful (serviço interno)

Page 148: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

node hookshot.js

API RESTful (pagar.me/docs)~ 500ms

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P> 5000 ms

~ 550 ms API RESTful (serviço interno)

Page 149: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

node hookshot.js

API RESTful (pagar.me/docs)~ 500ms

Redis (queue)

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P> 5000 ms

~ 550 ms API RESTful (serviço interno)

Page 150: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

node hookshot.js

API RESTful (pagar.me/docs)~ 500ms

Redis (queue)

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P> 5000 ms

~ 550 ms API RESTful (serviço interno)

Request HTTP para o servidor do cliente

Page 151: Node.js no Pagar.me

Cliente

node api.js -p 3000

node gateway.js -p 5000

node hookshot.js

API RESTful (pagar.me/docs)~ 500ms

Redis (queue)

XML, SOAP, ISO 8583, X25, sinal de fumaça… :P> 5000 ms

~ 550 ms API RESTful (serviço interno)

~ 100 msRequest HTTP para o servidor do cliente

Page 152: Node.js no Pagar.me

Deployment

Page 153: Node.js no Pagar.me

Nível 1

$ node server.js

n00bz… Processo não roda em background

Page 154: Node.js no Pagar.me

Nível 2

$ git pull && npm install && node server.js &

Opa… Agora tem Git, update das dependências pelo NPM e o processo roda em background

Page 155: Node.js no Pagar.me

Nível 3

$ git pull && npm install && nohup node server.js

Nohup roda o processo mesmo depois do logout do SSH

Page 156: Node.js no Pagar.me

Nível 4

$ git pull && npm install && service node-server restart

Um serviço é responsável por rodar e reiniciar o processo e salvar os logs do processo

Page 157: Node.js no Pagar.me

Nível 5

$ service node-server restart

Agora o servidor de CI lida com o Git e as dependências

Servidor de Continuous Integration (CI)

+

Page 158: Node.js no Pagar.me

pm2 (https://github.com/Unitech/pm2)

Page 159: Node.js no Pagar.me

pm2 (https://github.com/Unitech/pm2)

• Roda e gerencia os processos do Node.js (mantém processo rodando para sempre)

Page 160: Node.js no Pagar.me

pm2 (https://github.com/Unitech/pm2)

• Roda e gerencia os processos do Node.js (mantém processo rodando para sempre)

• Reload no código on-the-fly (zero downtime)

Page 161: Node.js no Pagar.me

pm2 (https://github.com/Unitech/pm2)

• Roda e gerencia os processos do Node.js (mantém processo rodando para sempre)

• Reload no código on-the-fly (zero downtime)

• Multi-thread e clusterização sem alterar uma linha de código

Page 162: Node.js no Pagar.me

pm2 (https://github.com/Unitech/pm2)

• Roda e gerencia os processos do Node.js (mantém processo rodando para sempre)

• Reload no código on-the-fly (zero downtime)

• Multi-thread e clusterização sem alterar uma linha de código

• Monitoramento e gerenciamento dos logs

Page 163: Node.js no Pagar.me

pm2 (https://github.com/Unitech/pm2)

• Roda e gerencia os processos do Node.js (mantém processo rodando para sempre)

• Reload no código on-the-fly (zero downtime)

• Multi-thread e clusterização sem alterar uma linha de código

• Monitoramento e gerenciamento dos logs

• API RESTful + interface web

Page 164: Node.js no Pagar.me

Nível 6

$ pm2 reload all

Strider é o servidor de CI e o pm2 reinicia o processo on-the-fly, sem perder nenhum request

Strider (servidor de CI)

+

Page 165: Node.js no Pagar.me

Nível 7 (ChatOps)

$ pm2 reload all

Janky é o servidor de CI, Heaven é o servidor de deployment e o pm2 reinicia o processo on-the-fly, sem perder nenhum request

Janky (Jenkins) + Heaven + Hubot

+

Page 166: Node.js no Pagar.me

ChatOps

Page 167: Node.js no Pagar.me

ChatOps

• Todos os commits são testados (via Janky + Jenkins)

Page 168: Node.js no Pagar.me

ChatOps

• Todos os commits são testados (via Janky + Jenkins)

• Todas as branches têm um estado (green/no-green)

Page 169: Node.js no Pagar.me

ChatOps

• Todos os commits são testados (via Janky + Jenkins)

• Todas as branches têm um estado (green/no-green)

• Todas as branches green podem ser deployadas (sem regressão)

Page 170: Node.js no Pagar.me

ChatOps

• Todos os commits são testados (via Janky + Jenkins)

• Todas as branches têm um estado (green/no-green)

• Todas as branches green podem ser deployadas (sem regressão)

• Tudo acontece integrado ao GitHub

Page 171: Node.js no Pagar.me

ChatOps

• Todos os commits são testados (via Janky + Jenkins)

• Todas as branches têm um estado (green/no-green)

• Todas as branches green podem ser deployadas (sem regressão)

• Tudo acontece integrado ao GitHub

• Deploy da branch X (via Heaven) para um servidor ou grupo de servidores

Page 172: Node.js no Pagar.me

ChatOps

• Todos os commits são testados (via Janky + Jenkins)

• Todas as branches têm um estado (green/no-green)

• Todas as branches green podem ser deployadas (sem regressão)

• Tudo acontece integrado ao GitHub

• Deploy da branch X (via Heaven) para um servidor ou grupo de servidores

• Tudo acontece numa sala de bate papo com todas as pessoas relacionadas ao projeto.

Page 173: Node.js no Pagar.me
Page 174: Node.js no Pagar.me

$ hubot ci build pagarme-api/boleto_upgrade

Page 175: Node.js no Pagar.me

$ hubot ci build pagarme-api/boleto_upgrade

$ hubot deploy pagarme-api/boleto_upgrade to prod-test/api01

Page 176: Node.js no Pagar.me

$ hubot ci build pagarme-api/boleto_upgrade

$ hubot deploy pagarme-api/boleto_upgrade to prod-test/api01

$ alias sharon=hubot

Page 177: Node.js no Pagar.me

$ alias sharon=hubot

$ sharon deploy pagarme-api/boleto_upgrade to prod-test/api01

$ sharon ci build pagarme-api/boleto_upgrade

Page 178: Node.js no Pagar.me
Page 179: Node.js no Pagar.me
Page 180: Node.js no Pagar.me

Conclusões…

Page 181: Node.js no Pagar.me
Page 182: Node.js no Pagar.me

PEDROFRANCESCHI @pedroh96

[email protected] github.com/pedrofranceschi

Obrigado! :)

Page 183: Node.js no Pagar.me

PEDROFRANCESCHI @pedroh96

[email protected] github.com/pedrofranceschi

Node.js no