Partilhar via


Guia de práticas recomendadas e solução de problemas para aplicativos de nó no Windows do Serviço de Aplicativo do Azure

Neste artigo, você aprenderá as práticas recomendadas e as etapas de solução de problemas para aplicativos do Windows Node.js executados no Serviço de Aplicativo do Azure (com iisnode).

Aviso

Tenha cuidado ao usar as etapas de solução de problemas em seu local de produção. A recomendação é solucionar problemas do aplicativo em uma configuração que não seja de produção, por exemplo, o slot de preparo e, quando o problema for corrigido, trocar o slot de preparo pelo slot de produção.

Configuração do IISNODE

Este arquivo de esquema mostra todas as configurações que você pode configurar para iisnode. Algumas das configurações que são úteis para o seu aplicativo:

nodeProcessCountPerApplication

Essa configuração controla o número de processos de nó iniciados por aplicativo IIS. O valor predefinido é 1. Você pode iniciar tantos node.exes quanto sua contagem de VM vCPU alterando o valor para 0. O valor recomendado é 0 para a maioria dos aplicativos para que você possa usar todas as vCPUs em sua máquina. Node.exe é single-threaded para que um node.exe consuma um máximo de 1 vCPU. Para obter o máximo desempenho do seu aplicativo de nó, você deseja usar todas as vCPUs.

nodeProcessCommandLine

Essa configuração controla o caminho para o node.exe. Você pode definir esse valor para apontar para sua versão node.exe.

maxConcurrentRequestsPerProcess

Essa configuração controla o número máximo de solicitações simultâneas enviadas pelo iisnode para cada node.exe. No Serviço de Aplicativo do Azure, o valor padrão é Infinito. Você pode configurar o valor dependendo de quantas solicitações seu aplicativo recebe e quão rápido seu aplicativo processa cada solicitação.

maxNamedPipeConnectionRetry

Essa configuração controla o número máximo de vezes que o iisnode tenta novamente fazer a conexão no pipe nomeado para enviar as solicitações para node.exe. Essa configuração em combinação com namedPipeConnectionRetryDelay determina o tempo limite total de cada solicitação no iisnode. O valor padrão é 200 no Serviço de Aplicativo do Azure. Tempo limite total em segundos = (maxNamedPipeConnectionRetry * namedPipeConnectionRetryDelay) / 1000

namedPipeConnectionRetryDelay

Essa configuração controla a quantidade de tempo (em ms) que o iisnode espera entre cada nova tentativa de enviar a solicitação para node.exe pelo pipe nomeado. O valor padrão é 250 ms. Tempo limite total em segundos = (maxNamedPipeConnectionRetry * namedPipeConnectionRetryDelay) / 1000

Por padrão, o tempo limite total no iisnode no Serviço de Aplicativo do Azure é 200 * 250 ms = 50 segundos.

logDiretório

Essa configuração controla o diretório onde iisnode logs stdout/stderr. O valor padrão é iisnode, que é relativo ao diretório de script principal (diretório onde o server.js principal está presente)

debuggerExtensionDll

Essa configuração controla qual versão do iisnode node-inspector usa ao depurar seu aplicativo de nó. Atualmente, iisnode-inspector-0.7.3.dll e iisnode-inspector.dll são os dois únicos valores válidos para essa configuração. O valor padrão é iisnode-inspector-0.7.3.dll. A versão iisnode-inspector-0.7.3.dll usa node-inspector-0.7.3 e usa soquetes da web. Habilite soquetes da Web em seu aplicativo Web do Azure para usar essa versão.

flushResponse [en]

O comportamento padrão do IIS é que ele armazena em buffer dados de resposta de até 4 MB antes da liberação ou até o final da resposta, o que ocorrer primeiro. iisnode oferece uma definição de configuração para substituir esse comportamento: para liberar um fragmento do corpo da entidade de resposta assim que iisnode recebê-lo de node.exe, você precisa definir o atributo iisnode/@flushResponse em web.config como 'true':

<configuration>
    <system.webServer>
        <!-- ... -->
        <iisnode flushResponse="true" />
    </system.webServer>
</configuration>

Habilitar a liberação de cada fragmento do corpo da entidade de resposta adiciona sobrecarga de desempenho que reduz a taxa de transferência do sistema em ~5% (a partir da v0.1.13). O melhor para definir o escopo dessa configuração apenas para pontos de extremidade que exigem streaming de resposta (por exemplo, usando o <location> elemento no web.config)

Além disso, para aplicativos de streaming, você também deve definir responseBufferLimit do manipulador iisnode como 0.

<handlers>
    <add name="iisnode" path="app.js" verb="\*" modules="iisnode" responseBufferLimit="0"/>
</handlers>

watchedFiles

Uma lista separada por ponto-e-vírgula de arquivos que são observados quanto a alterações. Qualquer alteração em um arquivo faz com que o aplicativo seja reciclado. Cada entrada consiste em um nome de diretório opcional, bem como um nome de arquivo necessário, que são relativos ao diretório onde o ponto de entrada do aplicativo principal está localizado. Os curingas são permitidos apenas na parte do nome do arquivo. O valor predefinido é *.js;iisnode.yml

recycleSignalEnabled

O valor predefinido é false. Se habilitado, seu aplicativo de nó pode se conectar a um pipe nomeado (variável de ambiente IISNODE_CONTROL_PIPE) e enviar uma mensagem de "reciclagem". Isso faz com que o w3wp seja reciclado graciosamente.

idlePageOutTimePeriod

O valor padrão é 0, o que significa que esse recurso está desabilitado. Quando definido como algum valor maior que 0, o iisnode paginará todos os seus processos filhos a cada 'idlePageOutTimePeriod' em milissegundos. Consulte a documentação para entender o que significa saída de página. Essa configuração é útil para aplicativos que consomem uma grande quantidade de memória e desejam distribuir memória para o disco ocasionalmente para liberar RAM.

Aviso

Tenha cuidado ao ativar as seguintes definições de configuração em aplicativos de produção. A recomendação é não habilitá-los em aplicativos de produção ao vivo.

debugHeaderEnabled

O valor predefinido é false. Se definido como true, iisnode adiciona um cabeçalho iisnode-debug de resposta HTTP a cada resposta HTTP que envia o valor do iisnode-debug cabeçalho é uma URL. Pedaços individuais de informações de diagnóstico podem ser obtidas olhando para o fragmento de URL, no entanto, uma visualização está disponível abrindo o URL em um navegador.

loggingEnabled

Essa configuração controla o registro de stdout e stderr por iisnode. O Iisnode captura stdout/stderr dos processos de nó que inicia e grava no diretório especificado na configuração 'logDirectory'. Depois que isso é habilitado, seu aplicativo grava logs no sistema de arquivos e, dependendo da quantidade de registro feito pelo aplicativo, pode haver implicações de desempenho.

devErrorsEnabled

O valor predefinido é false. Quando definido como true, o iisnode exibe o código de status HTTP e o código de erro Win32 no navegador. O código win32 é útil na depuração de certos tipos de problemas.

debuggingEnabled (não ativar no site de produção ao vivo)

Essa configuração controla o recurso de depuração. O Iisnode é integrado com o node-inspector. Ao habilitar essa configuração, você habilita a depuração do aplicativo do nó. Ao habilitar essa configuração, o iisnode cria arquivos node-inspector no diretório 'debuggerVirtualDir' na primeira solicitação de depuração para seu aplicativo de nó. Você pode carregar o node-inspector enviando uma solicitação para http://yoursite/server.js/debug. Você pode controlar o segmento de URL de depuração com a configuração 'debuggerPathSegment'. Por padrão, debuggerPathSegment='debug'. Você pode definir debuggerPathSegment como um GUID, por exemplo, para que seja mais difícil ser descoberto por outras pessoas.

Leia Depurar Node.js aplicativos no Windows para obter mais detalhes sobre depuração.

Cenários e recomendações/solução de problemas

Meu aplicativo de nó está fazendo chamadas de saída excessivas

Muitas aplicações gostariam de fazer ligações de saída como parte do funcionamento regular. Por exemplo, quando chega um pedido, a aplicação de nó gostaria de contactar uma API REST noutro local e obter algumas informações para processar o pedido. Gostaria de utilizar um agente keep alive ao fazer chamadas http ou https. Você pode usar o módulo agentkeepalive como seu agente keep alive ao fazer essas chamadas de saída.

O módulo agentkeepalive garante que os soquetes sejam reutilizados em sua VM do aplicativo Web do Azure. Criar um novo soquete em cada solicitação de saída adiciona sobrecarga ao seu aplicativo. Fazer com que seu aplicativo reutilize soquetes para solicitações de saída garante que seu aplicativo não exceda os maxSockets alocados por VM. A recomendação no Serviço de Aplicativo do Azure é definir o valor maxSockets do agentKeepAlive para um total de (4 instâncias de node.exe * 32 maxSockets/instância) 128 soquetes por VM.

Exemplo de configuração agentKeepALive :

let keepaliveAgent = new Agent({
    maxSockets: 32,
    maxFreeSockets: 10,
    timeout: 60000,
    freeSocketTimeout: 300000
});

Importante

Este exemplo pressupõe que você tenha 4 node.exe em execução em sua VM. Se você tiver um número diferente de node.exe em execução na VM, deverá modificar a configuração maxSockets de acordo.

Meu aplicativo de nó está consumindo muita CPU

Você pode receber uma recomendação do Serviço de Aplicativo do Azure em seu portal sobre alto consumo de cpu. Você também pode configurar monitores para observar determinadas métricas. Ao verificar o uso da CPU no Painel do portal do Azure, verifique os valores MAX da CPU para não perder os valores de pico. Se você acredita que seu aplicativo está consumindo muita CPU e não consegue explicar o porquê, você pode criar o perfil do seu aplicativo de nó para descobrir.

Criando o perfil do seu aplicativo de nó no Serviço de Aplicativo do Azure com o V8-Profiler

Por exemplo, digamos que você tenha um aplicativo hello world que deseja criar o seguinte perfil:

const http = require('http');
function WriteConsoleLog() {
    for(let i=0;i<99999;++i) {
        console.log('hello world');
    }
}

function HandleRequest() {
    WriteConsoleLog();
}

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    HandleRequest();
    res.end('Hello world!');
}).listen(process.env.PORT);

Vá para o site Debug Console https://yoursite.scm.azurewebsites.net/DebugConsole

Vá para o diretório site/wwwroot. Você verá um prompt de comando como mostrado no exemplo a seguir:

Captura de tela que mostra o diretório site/wwwroot e o prompt de comando.

Execute o comando npm install v8-profiler.

Este comando instala o v8-profiler em node_modules diretório e todas as suas dependências. Agora, edite seu server.js para criar o perfil do seu aplicativo.

const http = require('http');
const profiler = require('v8-profiler');
const fs = require('fs');

function WriteConsoleLog() {
    for(let i=0;i<99999;++i) {
        console.log('hello world');
    }
}

function HandleRequest() {
    profiler.startProfiling('HandleRequest');
    WriteConsoleLog();
    fs.writeFileSync('profile.cpuprofile', JSON.stringify(profiler.stopProfiling('HandleRequest')));
}

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/html'});
    HandleRequest();
    res.end('Hello world!');
}).listen(process.env.PORT);

O código anterior cria perfis da função WriteConsoleLog e, em seguida, grava a saída do perfil no arquivo 'profile.cpuprofile' em seu site wwwroot. Envie um pedido para a sua candidatura. Você vê um arquivo 'profile.cpuprofile' criado em seu site wwwroot.

Captura de tela que mostra o arquivo profile.cpuprofile.

Transfira este ficheiro e abra-o com as Ferramentas F12 do Chrome. Prima F12 no Chrome e, em seguida, selecione o separador Perfis . Escolha o botão Carregar . Selecione seu arquivo profile.cpuprofile que você baixou. Clique no perfil que acabou de carregar.

Captura de tela que mostra o arquivo profile.cpuprofile que você carregou.

Você pode ver que 95% do tempo foi consumido pela função WriteConsoleLog. A saída também mostra os números de linha exatos e os arquivos de origem que causaram o problema.

Meu aplicativo de nó está consumindo muita memória

Se seu aplicativo estiver consumindo muita memória, você verá um aviso do Serviço de Aplicativo do Azure em seu portal sobre alto consumo de memória. Você pode configurar monitores para observar determinadas métricas. Ao verificar o uso de memória no Painel do portal do Azure, verifique os valores MAX para memória para não perder os valores de pico.

Deteção de fugas e Heap Diff para Node.js

Você pode usar node-memwatch para ajudá-lo a identificar vazamentos de memória. Você pode instalar memwatch como v8-profiler e editar seu código para capturar e diferenciar pilhas para identificar os vazamentos de memória em seu aplicativo.

Meus node.exe estão sendo mortos aleatoriamente

Existem algumas razões pelas quais o node.exe é encerrado aleatoriamente:

  1. Seu aplicativo está lançando exceções não detetadas – Verifique o arquivo d:\home\LogFiles\Application\logging-errors.txt para obter os detalhes sobre a exceção lançada. Este arquivo tem o rastreamento de pilha para ajudar a depurar e corrigir seu aplicativo.
  2. Seu aplicativo está consumindo muita memória, o que está afetando outros processos desde o início. Se a memória total da VM estiver próxima de 100%, os node.exe poderão ser mortos pelo gerenciador de processos. O gestor de processos mata alguns processos para permitir que outros tenham a oportunidade de fazer algum trabalho. Para corrigir esse problema, crie o perfil do seu aplicativo para vazamentos de memória. Se o seu aplicativo requer grandes quantidades de memória, dimensione para uma VM maior (o que aumenta a RAM disponível para a VM).

Meu aplicativo de nó não inicia

Se o seu aplicativo estiver retornando 500 erros quando for iniciado, pode haver alguns motivos:

  1. Node.exe não está presente no local correto. Verifique a configuração nodeProcessCommandLine.
  2. O arquivo de script principal não está presente no local correto. Verifique web.config e verifique se o nome do arquivo de script principal na seção handlers corresponde ao arquivo de script principal.
  3. A configuração Web.config não está correta – verifique os nomes/valores das configurações.
  4. Arranque a frio – A sua aplicação está a demorar demasiado tempo a iniciar. Se seu aplicativo demorar mais do que (maxNamedPipeConnectionRetry * namedPipeConnectionRetryDelay) / 1000 segundos, iisnode retornará um erro 500. Aumente os valores dessas configurações para corresponder à hora de início do aplicativo para evitar que o iisnode atinja o tempo limite e retorne o erro 500.

Meu aplicativo de nó falhou

Seu aplicativo está lançando exceções não detetadas – Verifique d:\\home\\LogFiles\\Application\\logging-errors.txt o arquivo para obter os detalhes sobre a exceção lançada. Este arquivo tem o rastreamento de pilha para ajudar a diagnosticar e corrigir seu aplicativo.

Meu aplicativo de nó leva muito tempo para iniciar (Cold Start)

A causa comum para longos tempos de início de aplicativos é um alto número de arquivos no node_modules. O aplicativo tenta carregar a maioria desses arquivos ao iniciar. Por padrão, como seus arquivos são armazenados no compartilhamento de rede no Serviço de Aplicativo do Azure, carregar muitos arquivos pode levar tempo. Algumas soluções para tornar este processo mais rápido são:

  1. Tente carregar com preguiça o node_modules e não carregar todos os módulos no início do aplicativo. Para módulos de carga preguiçosa, a chamada para require('module') deve ser feita quando você realmente precisa do módulo dentro da função antes da primeira execução do código do módulo.
  2. O Serviço de Aplicativo do Azure oferece um recurso chamado cache local. Esse recurso copia seu conteúdo do compartilhamento de rede para o disco local na VM. Como os arquivos são locais, o tempo de carregamento do node_modules é muito mais rápido.

IISNODE http status e substatus

O cnodeconstants arquivo de origem lista todas as combinações possíveis de status/substatus que o iisnode pode retornar devido a um erro.

Habilite o FREB para seu aplicativo para ver o código de erro win32 (certifique-se de habilitar o FREB somente em locais que não sejam de produção por motivos de desempenho).

Http Status Http Substatus Possível motivo?
500 1000 Houve algum problema ao enviar a solicitação para o IISNODE – Verifique se node.exe foi iniciado. Node.exe poderia ter falhado ao iniciar. Verifique se há erros na configuração do web.config.
500 1001 - Win32Error 0x2 - O aplicativo não está respondendo ao URL. Verifique as regras de reconfiguração de URL ou verifique se o seu aplicativo expresso tem as rotas corretas definidas. - Win32Error 0x6d – pipe nomeado está ocupado – Node.exe não está aceitando solicitações porque o pipe está ocupado. Verifique o alto uso da cpu. - Outros erros – verifique se node.exe travou.
500 1002 Node.exe falhou – verifique d:\home\LogFiles\logging-errors.txt para rastreamento de pilha.
500 1003 Problema de configuração do pipe – A configuração do pipe nomeado está incorreta.
500 1004-1018 Ocorreu algum erro ao enviar o pedido ou ao processar a resposta de/para node.exe. Verifique se node.exe travou. verifique d:\home\LogFiles\logging-errors.txt para rastreamento de pilha.
503 1000 Não há memória suficiente para alocar mais conexões de pipe nomeadas. Verifique por que seu aplicativo está consumindo tanta memória. Verifique o valor da configuração maxConcurrentRequestsPerProcess. Se não for infinito e você tiver muitas solicitações, aumente esse valor para evitar esse erro.
503 1001 Não foi possível enviar a solicitação para node.exe porque o aplicativo está sendo reciclado. Após a reciclagem do pedido, os pedidos devem ser atendidos normalmente.
503 1002 Verifique o código de erro win32 por motivo real – A solicitação não pôde ser enviada para um node.exe.
503 1003 O pipe nomeado está muito ocupado – Verifique se node.exe está consumindo CPU excessiva

NODE.exe tem uma configuração chamada NODE_PENDING_PIPE_INSTANCES. No Serviço de Aplicativo do Azure, esse valor é definido como 5000. O que significa que node.exe pode aceitar 5000 solicitações de cada vez no pipe nomeado. Esse valor deve ser bom o suficiente para a maioria dos aplicativos de nó em execução no Serviço de Aplicativo do Azure. Você não deve ver 503.1003 no Serviço de Aplicativo do Azure devido ao alto valor para o NODE_PENDING_PIPE_INSTANCES

Mais recursos

Siga estes links para saber mais sobre Node.js aplicativos no Serviço de Aplicativo do Azure.