nodejs in production

Post on 19-Feb-2017

257 Views

Category:

Software

2 Downloads

Preview:

Click to see full reader

TRANSCRIPT

NodeJS in Production

William BrunoDesenvolvedor NodeJS

http://wbruno.com.br/ http://github.com/wbruno wbrunom@gmail.com @wbrunom

use istanbul use jshint

relatório de cobertura dos seus testes análise estática de código, check de sintaxe

seja rápidoSeja extremamente rápido, quanto menos tempo de NodeJS sua

aplicação tiver, mais ela irá escalar. Assíncrono

Single Thread V8 usa no máximo 1.6GB de RAM por processo

Consome pouca RAM e pouca CPU

use clusterif (cluster.isMaster) { for (let i = 0; i < numCPUs; i++) { let worker = cluster.fork(); worker.on('error', _onWorkerError); } } else { //… }

use Objetos Literaislet AccountController = { login: function doLogin(request, response, next) { //.. } };

module.exports = AccountController;

require() é síncrono, cacheado e singleton

use gzipapp.use(compression());

não use módulos desnecessárioshelmet

lodash/undescore

app.disable('etag'); app.disable('x-powered-by');

outros cabeçalhos no nginx

use programação funcional[].filter(); [].map(); [].some(); [].every(); [].find(); [].reduce(); Monads, clousures, currying, HOF, avoid side-effects, etc

use es6Nativa desde o NodeJS 4.0

Esqueça Babel

'use strict'; let express = require('express');

use mozilla/nunjucksÓtimo template engine

Mantido pela Fundação Mozilla

nomeie seus middlewaresapp.get('/', function getHome(request, response, next) { response.send('Home'); });

erros num único pontoTrate os erros num único lugar

app.use(function handleError(err, request, response, next) { response.status(err.status || 500);

//log if (request.xhr) { response.json({ err: err.message }); } else { response.render('error', { message: err.message }); } });

use debugNão deixe console.log() perdidos no código

Tudo o que vai para o std output escreve no log

escreva logwinston [splunk, graylog]

quem, quando, o quê

use newrelicSERVER

APMBROWSER

use a lib bluebirdMais rápida que a implementação nativa de Promise

Possui o método .promisifyAll()

use npm scripts{ "name": "app", "scripts": { "gulp": "gulp; ./scripts.sh akamai; gulp s3", "jshint": "jshint server/*", "karma": "./scripts.sh karma", "nodemon": "nodemon ./server/bin/www", "patch": "npm version patch -m \"release: version %s\" && git push --tags && git push", "start": "./scripts.sh start", "test": "./scripts.sh test" },

use npm scripts#!/bin/bash

BROWSER=${2:-"PhantomJS"}

case "$1" in start) echo 'Starting...' export DEBUG=blz:* bower install npm-run-all --parallel gulp-watch karma ;; test) echo 'Testing backend...' gulp eslint:nodejs export DEBUG=blz:* ./node_modules/istanbul/lib/cli.js cover ./node_modules/mocha/bin/_mocha test/nodejs/* ;; karma) echo 'Testing frontend...' gulp eslint:angular gulp eslint:jquery ./node_modules/karma/bin/karma start --browsers $BROWSER ./test/angular/karma.conf.js ;; akamai) echo 'Updating akamai...' export APPLICATION_VERSION=$(node -e "console.log(require('./package.json').version);") mkdir -p _akamai/$APPLICATION_VERSION cp -r dist/public/* _akamai/$APPLICATION_VERSION

chmod 400 akamai.key scp -i akamai.key -o StrictHostKeyChecking=no -rp _akamai/$APPLICATION_VERSION user@..…upload.akamai.com:/dir/ ;; *) echo "Usage: {start|akamai|test|karma}" exit 1 ;; esac

use forever para prod e nodemon para dev

use /etc/init.d/nodejs ou /etc/init/nodejs

Unix Service ou Ubuntu upstart

https://github.com/wbruno/examples/tree/gh-pages/nodejs-in-production

https://github.com/wbruno/examples/tree/gh-pages/nodejs-in-production

#!/bin/sh

### BEGIN INIT INFO # Provides: nodejs init script # Required-Start: forever node module # X-Interactive: true # Short-Description: application initscript # Description: Uses forever module to running the application ### END INIT INFO

NODE_ENV="{{ enviroment }}" PORT="3002" APP_DIR="/var/{{ application }}/dist/server" NODE_APP="bin/www" CONFIG_DIR="$APP_DIR/config" LOG_DIR="/var/log/{{ application }}" LOG_FILE="$LOG_DIR/app.log" NODE_EXEC="forever"

###############

USAGE="Usage: $0 {start|stop|restart|status}"

start_app() { mkdir -p "$LOG_DIR"

echo "Starting node app ..." PORT="$PORT" NODE_ENV="$NODE_ENV" NODE_CONFIG_DIR="$CONFIG_DIR" forever start "$APP_DIR/$NODE_APP" 1>"$LOG_FILE" 2>&1 & } stop_app() { forever stop "$APP_DIR/$NODE_APP" } status_app() { forever list } restart_app() { forever restart "$APP_DIR/$NODE_APP" }

case "$1" in start) start_app ;; stop) stop_app ;; restart) restart_app ;; status) status_app ;; *) echo $USAGE exit 1 ;; esac

Unix service

https://github.com/wbruno/examples/tree/gh-pages/nodejs-in-production

start on filesystem and started networking stop on shutdown

expect fork

setuid www-data env HOME="/var/{{ application }}"

env NODE_ENV="{{ enviroment }}" env MIN_UPTIME="5000" env SPIN_SLEEP_TIME="2000"

chdir /var/{{ application }}/dist/server env APP_EXEC="bin/www"

script exec forever -a -l $HOME/forever.log --minUptime=$MIN_UPTIME --spinSleepTime=$SPIN_SLEEP_TIME start $APP_EXEC end script

pre-stop script exec forever stopall end script

Ubuntu upstart

use o nginx-fullÓtimo web server

Ultra rápido Assíncrono, não bloqueante

Super configurável http2 (server push apenas no plus)

https://github.com/wbruno/examples/tree/gh-pages/nodejs-in-production

server { listen 80; server_name www.{{ domain }}; access_log /var/{{ application }}/www.{{ domain }}-access.log; error_log /var/{{ application }}/www.{{ domain }}-error.log;

proxy_cache one;

root /var/{{ application }}/dist/public/;

error_page 400 404 414 500 502 503 504 /50x.html;

location /50x.html { internal; }

location /api { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host; proxy_pass http://nodejs/api; }

location ~* \.(?:ico|css|html|json|js|gif|jpe?g|png|ttf|woff|woff2|svg|eot|txt)$ { access_log off; expires 14d; add_header Pragma public; add_header Cache-Control "public, mustrevalidate, proxy-revalidate"; root /var/{{ application }}/dist/public; }

}

location / { add_header X-Cache-Status $upstream_cache_status; add_header Strict-Transport-Security "max-age=1440; includeSubdomains";

expires 60s;

set $mobile ‘@desktop'; if ($http_user_agent ~* "...") { set $mobile "@tablet"; } if ($http_user_agent ~* "...") { set $mobile "@smartphone"; } proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $host;

proxy_ignore_headers Cache-Control;

proxy_pass http://nodejs;

proxy_cache_key "$mobile$scheme://$host$request_uri"; proxy_cache_bypass $cookie_nocache $arg_nocache;

proxy_cache_valid 1m; proxy_cache_min_uses 1; }

https://github.com/wbruno/examples/tree/gh-pages/nodejs-in-production

http { sendfile on;

tcp_nopush on; tcp_nodelay on;

keepalive_timeout 60; send_timeout 60;

client_body_timeout 60; client_header_timeout 60; client_body_buffer_size 10K; client_header_buffer_size 1k; client_max_body_size 8m;

large_client_header_buffers 4 32k; types_hash_max_size 2048;

server_tokens off; server_names_hash_bucket_size 64;

default_type application/octet-stream; log_format elb '$http_x_forwarded_for - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"'; access_log /var/log/nginx/access.log; error_log /var/log/nginx/error.log;

proxy_cache_path /tmp/cache keys_zone=one:10m loader_threshold=100 loader_files=100 loader_sleep=30 inactive=30m max_size=2g;

charset utf-8;

gzip on; gzip_disable "msie6"; gzip_min_length 1; gzip_types *;

gzip_http_version 1.1; gzip_vary on; gzip_comp_level 6; gzip_proxied any; gzip_buffers 16 8k;

include /etc/nginx/mime.types; include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; include /etc/nginx/upstreams.d/nodejs; }

user www-data; worker_processes auto; pid /run/nginx.pid;

events { worker_connections 1024; multi_accept on; use epoll; }

Bibliografiahttps://promisesaplus.com https://blog.risingstack.com/node-js-best-practices/ https://www.sitepoint.com/10-tips-make-node-js-web-app-faster/ http://expressjs.com/en/advanced/best-practice-performance.html https://www.packtpub.com/books/content/fine-tune-nginx-configufine-tune-nginx-configurationfine-tune-nginx-configurationratio https://www.nginx.com/blog/nginx-caching-guide/

https://github.com/wbruno/examples/tree/gh-pages/nodejs-in-production

Obrigado

top related