Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Nodejs in Production

732 vues

Publié le

Dicas para publicar e manter sua aplicação NodeJS em produção. Configure o Express corretamente, trate erros, use o Nginx no seu máximo, monitore sua aplicação javascript server-side com newrelic e logs.

Publié dans : Logiciels
  • Soyez le premier à commenter

Nodejs in Production

  1. 1. NodeJS in Production
  2. 2. William Bruno Desenvolvedor NodeJS http://wbruno.com.br/ http://github.com/wbruno wbrunom@gmail.com @wbrunom
  3. 3. use istanbul use jshint relatório de cobertura dos seus testes análise estática de código, check de sintaxe
  4. 4. seja rápido Seja 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
  5. 5. use cluster if (cluster.isMaster) { for (let i = 0; i < numCPUs; i++) { let worker = cluster.fork(); worker.on('error', _onWorkerError); } } else { //… }
  6. 6. use Objetos Literais let AccountController = { login: function doLogin(request, response, next) { //.. } }; module.exports = AccountController; require() é síncrono, cacheado e singleton
  7. 7. use gzip app.use(compression());
  8. 8. não use módulos desnecessários helmet lodash/undescore app.disable('etag'); app.disable('x-powered-by'); outros cabeçalhos no nginx
  9. 9. use programação funcional [].filter(); [].map(); [].some(); [].every(); [].find(); [].reduce(); Monads, clousures, currying, HOF, avoid side-effects, etc
  10. 10. use es6 Nativa desde o NodeJS 4.0
 Esqueça Babel 'use strict'; let express = require('express');
  11. 11. use mozilla/nunjucks Ótimo template engine Mantido pela Fundação Mozilla
  12. 12. nomeie seus middlewares app.get('/', function getHome(request, response, next) { response.send('Home'); });
  13. 13. erros num único ponto Trate 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 }); } });
  14. 14. use debug Não deixe console.log() perdidos no código Tudo o que vai para o std output escreve no log
  15. 15. escreva log winston [splunk, graylog] quem, quando, o quê
  16. 16. use newrelic SERVER
 APM
 BROWSER
  17. 17. use a lib bluebird Mais rápida que a implementação nativa de Promise
 Possui o método .promisifyAll()
  18. 18. 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" },
  19. 19. 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
  20. 20. use forever para prod e nodemon para dev
  21. 21. 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
  22. 22. 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
  23. 23. 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
  24. 24. use o nginx-full Ótimo web server Ultra rápido Assíncrono, não bloqueante Super configurável http2 (server push apenas no plus)
  25. 25. 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; }
  26. 26. 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; }
  27. 27. Bibliografia https://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
  28. 28. Obrigado

×