Implementando e escalonando o aplicativo NodeJS com tempo de inatividade zero

<a href=” http://nodejs.org”> NodeJS </a> é uma plataforma javascript de E / S não bloqueadora e orientada a eventos. Agora, nodejs tem <a href=” http://nodeframework.com/”> 30+ frameworks ou bibliotecas </a> que você pode usar para construir uma aplicação web leve. A questão é: como implantar nosso aplicativo nodeJS no servidor de teste ou de produção?


Torne seu aplicativo escalonável

Eu estava pensando em como fazer um aplicativo escalonável com base na CPU total do meu servidor. Preciso do módulo de cluster para inicializar meu aplicativo. Por exemplo, caso, por padrão, terei 1 execução principal para processar a solicitação e, em seguida, N trabalhadores bifurcam a principal para lidar com a solicitação com processos bifurcados. Obrigado a Johnny Domino que construiu o node-clusterap , mas eu preciso revisar uma pequena coisa devido ao problema de umask e permissão de arquivo sock.

exemplo de agrupamento em express.io

var express = require('express.io'),
Clustrap = require('clustrap'),
app
= express(),
httpOptions
= {
workers
: 3,
port
: 3000
},
environment
= process.env.NODE_ENV || 'development';

if(environment !== 'development'){
httpOptions
.sock = './tmp/sockets/app.sock';
}

app
.http().io();

app
.get('/', function(req, res, next){
res
.send('I am in '+environment);
})

var service = new Clustrap(app, httpOptions);
service
.listen();

O código cortado acima diz ao aplicativo para bifurcar 3 workers e escutar na porta 3000 para o servidor http e soquete io se o ambiente for desenvolvimento, mas escutar o arquivo de soquete e pular a escuta da porta se o ambiente não for desenvolvimento. Se você não fornecer number worker, ele bifurcará o worker tanto quanto a cpu total no servidor. Prefiro usar o arquivo sock porque não preciso pensar em portas de firewall para rodar meu aplicativo.


Configurar script de implantação

Estas são algumas alternativas para implantar o aplicativo nodejs:

<ul>
<li>
<strong> Capistrano </strong>
<ul>
<li> speak: ruby ​​</li>
<li> fonte: http://github.com/capistrano/capistrano </li>
</ ul >
</li>
<li>
<strong> Mina </strong>
<ul>
<li> speak: ruby ​​</li>
<li> fonte: http://github.com/mina-deploy/mina </ li >
</ul>
</li>
<li>
<strong> Minco </strong>
<ul>
<li> speak: nodejs </li>
<li>fonte: http://github.com/dsmatter/minco </li>
</ul>
</li>
<li>
<strong> Mina JS </strong>
<ul>
<li> speak: nodejs </li>
<li> fonte: http://github.com/CenturyUna/mina </li>
</ul>
< / li>
</ul>

Porque eu falo Javascript, não quero instalar Ruby ou qualquer mecanismo em minhas máquinas locais e servidores apenas para uma implantação. Então minha decisão vai para <b> Mina JS </b>, é baseado no Minco e inspirado em Mina Ruby. O Capistrano é incrível e completo, muito complicado para novatos como eu e ruby ​​não é JS.

etapa 1: instale o mina na máquina de implantação

$ npm install -g mina

etapa 2: inicializar o pacote de implantação

$ cd /path/to/dev_app
$ mina init

etapa 3: pacote de implantação de instalação com tempo de inatividade zero ao reiniciar o aplicativo

{

"server": "user@127.0.0.1",

"server_dir": "/path/to/production_dir",

"repo": "git@github.com:youraccount/project.git",

"prj_git_relative_dir": "",

"branch": "production",

"force_regenerate_git_dir": false,

"shared_dirs": [
"node_modules",
"logs",
"tmp",
"public/uploads"
],

"history_releases_count": 5,

"prerun": [
"npm install",
"npm test",
"ln -s config/database.js /path/to/production_dir/shared/config/database.js",
"cp tmp/pids/app.pid tmp/pids/app.pid.old || true"
],

"run_cmd": "NODE_ENV=production node server > /dev/null 2>&1 & echo $! > tmp/pids/app.pid; kill -15 `cat tmp/pids/app.pid.old` || true"
}

O código acima é escrito no arquivo deploy.json depois que você executa o mina init, o formato é json. Deixe-me explicar um pouco sobre as chaves de json acima:

  • servidor é um endereço para implantar seu aplicativo. Ele usará o login ssh, você pode adicionar sua chave ssh a .ssh / authorized_keys no seu servidor, então quando a implantação não será solicitada a inserir uma senha.

  • server_dir é um endereço de caminho para implantar seu aplicativo neste dir no servidor.

  • repo é um endereço de repositório git, suporta apenas git agora.

  • prj git diretório relativo é a localização do projeto em seu repositório git se você tiver mais de um projeto no mesmo endereço git.

  • branch é um branch a ser verificado e implantado a partir de seu endereço do github.

  • force regenerate git dir está forçando a reclone do repositório a cada vez que o desenvolvimento, por padrão é false.

  • shared_dirs is diretórios de seu projeto nesta matriz usará um simbólico em vez de criar toda vez que executar o deploy. Os diretórios compartilhados são geralmente usados ​​por cada versão de lançamento, de modo que você não terá tudo nesta pasta, por exemplo, arquivos de log na pasta de logs, arquivo pid, arquivo sock, arquivos de cache na pasta tmp ou node_modules.

  • A contagem de lançamentos do histórico é sobre quantos instantâneos de lançamento evitam a limpeza automática; por padrão, são 10 lançamentos se não fornecidos.

  • prerun é uma lista de linhas de comando para executar scripts de personalização antes de executar o aplicativo. Na pré-execução, escrevi , isso significa que copiei o arquivo de identificação do processo existente para outro arquivo, de modo que possa usá-lo para encerrar o servidor ativo após o lançamento da nova versão.cp tmp/pids/app.pid tmp/pids/app.pid.old || true

  • run_cmd é um comando para iniciar seu projeto. Você pode usar o Forever para garantir que seu servidor de nó seja executado continuamente, em vez de nohub ou script bash com &.


configurar diretórios de implantação

Vamos deixar o desenvolvimento ou a máquina local no momento e fazer o login em seu servidor de implantação. Presumo que você tenha usuário e diretório para implantação, por favor, não use root por razões de segurança. Vá para o diretório inicial do usuário e crie o diretório de produção ou implantação. Normalmente, eu construo alguns subdiretórios em meu diretório de implantação.

- production_dir
- releases
- shared
- config
- tmp
- sockets
- pids
- caches
- public
- uploads

Deixe-me explicar para que servem essas pastas:

  • shared / config é o diretório para armazenar a configuração de seu aplicativo, por exemplo, database.js, twitter_info.js, redis.js e etc.

  • shared / public / uploads é o diretório para armazenar arquivos carregados se o seu aplicativo tiver negócios de processo para fazer upload de arquivo e armazená-lo no servidor

  • tmp / sockets é o diretório para armazenar o arquivo sock que será criado após a execução do servidor http.

  • tmp / pids é o diretório para armazenar o arquivo pid

  • tmp / caches é o diretório para armazenar cookies ou arquivos de cache se você usar armazenamento de arquivo em vez de armazenamento de memória.

  • releases é o diretório para armazenar o aplicativo de histórico por versão de lançamento.


preparar pré-compilar ativos

Eu sugiro que você use o nginx como seu servidor http principal, porque ele oferece suporte a eventos, assíncronos e 10K amigável. Também estou interessado em implementar a pré-compilação de ativos como Ruby fez. Você pode usar o destruidor de ativos para pré -compilar seus arquivos de ativos estáticos na máquina local. Mas ele não pode lidar com ativos dinâmicos pré-compilar em tempo de execução.

Para lidar com a pré-compilação de ativos dinâmicos, descobri que o ngx_pagespeed otimiza automaticamente os ativos na primeira vez que a página é aberta. Compilar ativos é importante para armazenar em cache os arquivos de ativos em seu navegador por sua versão.


configurar o balanceamento de carga do nginx

Para instalar o módulo ngx_pagespeed, você pode seguir as instruções em sua página github . Depois que seu nginx estiver instalado, você precisará criar um arquivo de configuração para seu site, aqui está minha configuração em ou diretório após reiniciar o nginx:/usr/locals/nginx/sites-available/etc/nginx/sites-available

upstream nodejs_stream {
# comment this line if you use port
server unix
:/path/to/production_dir/current/tmp/sockets/app.sock fail_timeout=0;
# uncomment this line if you use port
#server 127.0.0.1:3000 fail_timeout=0;
}

server
{
listen
80;
server_name your
-website.com;
root
/path/to/production_dir/current/public;
try_files $uri
/system/maintenance.html @nodejs_stream;

location
@nodejs_stream {
proxy_set_header X
-Real-IP $remote_addr;
proxy_set_header X
-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X
-Forwarded-Proto $scheme;
proxy_set_header
Host $http_host;
proxy_set_header X
-NginX-Proxy true;

proxy_redirect off
;
proxy_pass http
://nodejs_stream;

proxy_http_version
1.1;
proxy_set_header
Upgrade $http_upgrade;
proxy_set_header
Connection "upgrade";


access_log
/path/to/production_dir/current/logs/nginx.access.log;
error_log
/path/to/production_dir/current/logs/nginx.error.log;

# remove or comment app pagespeed configuration if you not use it
pagespeed on
;

# it will precompile new assets each time application released, for best result please use tmpfs directory
pagespeed
FileCachePath /path/to/production_dir/current/public/;

# Ensure requests for pagespeed optimized resources go to the pagespeed
# handler and no extraneous headers get set.
location
~ ".pagespeed.([a-z].)?[a-z]{2}.[^.]{10}.[^.]+" { add_header "" ""; }
location
~ "^/ngx_pagespeed_static/" { }
location
~ "^/ngx_pagespeed_beacon$" { }
location
/ngx_pagespeed_statistics { allow 127.0.0.1; deny all; }
location
/ngx_pagespeed_global_statistics { allow 127.0.0.1; deny all; }
location
/ngx_pagespeed_message { allow 127.0.0.1; deny all; }
location
/pagespeed_console { allow 127.0.0.1; deny all; }
}
}

Configurar servidor com tempo de inatividade zero com Monit

Eu uso o Monit para monitorar o processo do sistema e a recuperação de erros no servidor de implantação. Monit é mais fácil de instalar por meio do apt-get:

sudo apt-get install monit

você pode adicionar arquivos de configuração monit em /etc/monit/monitrc/

Monitrc Script para aplicativo NodeJS

# save to /etc/monit/monitrc/monit_nodeapp.conf
check process monit_nodeapp
with pidfile /path/to/production_dir/current/tmp/pids/app.pid
group staff
start program
= "/path/to/production_dir/current/config/monit_nodeapp.start"
as uid deploy and gid staff
stop program
= "/path/to/production_dir/current/config/monit_nodeapp.stop"
as uid deploy and gid staff
if failed unixsocket /path/to/production_dir/current/tmp/sockets/app.sock
protocol HTTP request
"/?status" for 5 cycles then restart

Monit script binário para iniciar seu aplicativo se encerrado inesperadamente

#!/bin/bash
# save in /path/to/production_dir/current/config/monit_nodeapp.start
echo
"Start NodeJS App:"
echo
" [+] Enter directory /path/to/production_dir/current"
cd
/path/to/production_dir/current
echo
" [+] Run NodeJS script"
exec
`NODE_ENV=production node server > /dev/null 2>&1 & echo $! > tmp/pids/app.pid`
echo
" [+] Done !!"

Monit script binário para parar seu aplicativo se nenhuma resposta ou travar

#!/bin/bash
# save in /path/to/production_dir/current/config/monit_nodeapp.stop
echo
"Stop NodeJS App:"
echo
" [+] Enter directory /path/to/production_dir/current"
cd
/path/to/production_dir/current
echo
" [+] Run Termination script"
exec
`kill -15 `cat /path/to/production_dir/current/tmp/pids/app.pid` || true`
echo
" [+] Done !!"

Você pode verificar aqui a instalação do Monit Configuration com scripts binários de início e parada para Nginx, PostgreSQL, Redis.

Em seguida, recarregue o seu monitor

sudo monit reload

É hora de implantar

De volta à sua máquina de desenvolvimento e à pasta do aplicativo, execute este comando

mina deploy

Assim que o processo for concluído, você pode ver no servidor de implantação uma pasta “atual” em sua pasta de implantação que está vinculada à pasta da versão lançada após abrir seu domínio no navegador. Para os códigos de exemplo deste conhecimento de compartilhamento, você pode verificar meu github

Muito obrigado por visitar meu mural, se você gostou, por favor, compartilhe este mural. Se você tiver algum comentário, por favor deixe-me uma mensagem. saúde ^ _ ^