node.js - started - starting a node js project




Como, em geral, o Node.js lida com 10.000 solicitações simultâneas? (4)

Entendo que o Node.js usa um thread único e um loop de eventos para processar solicitações que processam apenas uma por vez (que é sem bloqueio).

Eu poderia estar entendendo mal o que você disse aqui, mas "um de cada vez" parece que você pode não estar entendendo completamente a arquitetura baseada em eventos.

Em uma arquitetura de aplicativo "convencional" (não orientada a eventos), o processo passa muito tempo esperando que algo aconteça. Em uma arquitetura baseada em eventos como o Node.js, o processo não apenas espera, ele pode continuar com outro trabalho.

Por exemplo: você obtém uma conexão de um cliente, aceita, lê os cabeçalhos da solicitação (no caso de http) e começa a agir sobre a solicitação. Você pode ler o corpo da solicitação; geralmente, você envia alguns dados de volta ao cliente (isso é uma simplificação deliberada do procedimento, apenas para demonstrar o ponto).

Em cada um desses estágios, a maior parte do tempo é gasta aguardando a chegada de alguns dados do outro lado - o tempo real gasto no processamento no encadeamento JS principal é geralmente bastante mínimo.

Quando o estado de um objeto de E / S (como uma conexão de rede) muda de forma a precisar de processamento (por exemplo, dados são recebidos em um soquete, um soquete se torna gravável etc.), o principal encadeamento JS do Node.js. é acordado com uma lista de itens que precisam ser processados.

Ele encontra a estrutura de dados relevante e emite algum evento nessa estrutura que faz com que os retornos de chamada sejam executados, que processam os dados recebidos ou gravam mais dados em um soquete etc. Depois que todos os objetos de E / S que precisam de processamento tiverem sido processado, o principal encadeamento JS do Node.js. esperará novamente até que seja informado que mais dados estão disponíveis (ou que alguma outra operação foi concluída ou atingiu o tempo limite).

Na próxima vez em que for ativado, poderá ser devido a um objeto de E / S diferente que precisa ser processado - por exemplo, uma conexão de rede diferente. A cada vez, os retornos de chamada relevantes são executados e, em seguida, ele volta a dormir esperando que algo mais aconteça.

O ponto importante é que o processamento de solicitações diferentes é intercalado, ele não processa uma solicitação do início ao fim e depois passa para a próxima.

Na minha opinião, a principal vantagem disso é que uma solicitação lenta (por exemplo, você está tentando enviar 1 MB de dados de resposta para um telefone celular por uma conexão de dados 2G ou está fazendo uma consulta muito lenta ao banco de dados) ganhou ' Não bloqueie os mais rápidos.

Em um servidor Web multithread convencional, você normalmente terá um thread para cada solicitação sendo processada e processará APENAS essa solicitação até que seja concluída. O que acontece se você tiver muitos pedidos lentos? Você acaba com muitos encadeamentos processando esses pedidos, e outros pedidos (que podem ser pedidos muito simples que podem ser tratados muito rapidamente) ficam na fila atrás deles.

Existem muitos outros sistemas baseados em eventos além do Node.js, e eles tendem a ter vantagens e desvantagens semelhantes em comparação com o modelo convencional.

Eu não diria que os sistemas baseados em eventos são mais rápidos em todas as situações ou em todas as cargas de trabalho - eles tendem a funcionar bem para cargas de trabalho ligadas a E / S, não tão bem para as associadas a CPU.

Entendo que o Node.js usa um thread único e um loop de eventos para processar solicitações que processam apenas uma por vez (que é sem bloqueio). Mas, ainda assim, como isso funciona, digamos 10.000 solicitações simultâneas. O loop de eventos processará todas as solicitações? Isso não levaria muito tempo?

Ainda não consigo entender como pode ser mais rápido do que um servidor da web com vários threads. Entendo que o servidor da web multiencadeado será mais caro em recursos (memória, CPU), mas ainda não seria mais rápido? Provavelmente estou errado; explique como esse thread único é mais rápido em muitas solicitações e o que normalmente faz (em alto nível) ao atender a muitas solicitações, como 10.000.

E também, essa linha única será bem dimensionada com essa grande quantidade? Lembre-se de que estou começando a aprender o Node.js.


Adicionando à resposta do slebetman: Quando você diz que o Node.JS pode lidar com 10.000 solicitações simultâneas, elas são essencialmente solicitações sem bloqueio, ou seja, essas solicitações pertencem principalmente à consulta ao banco de dados.

Internamente, o event loop de event loop do Node.JS está manipulando um thread pool , onde cada encadeamento lida com uma non-blocking request e o loop de eventos continua a escutar mais solicitações após delegar trabalho a um dos encadeamentos do thread pool . Quando um dos encadeamentos conclui o trabalho, ele envia um sinal para o event loop que terminou o chamado callback . Event loop processa esse retorno de chamada e envia a resposta de volta.

Como você é novo no NodeJS, leia mais sobre o nextTick para entender como o loop de eventos funciona internamente. Leia os blogs em http://javascriptissexy.com , eles foram realmente úteis para mim quando comecei com JavaScript / NodeJS.


Se você precisar fazer essa pergunta, provavelmente não está familiarizado com o que a maioria dos aplicativos / serviços da Web faz. Você provavelmente está pensando que todos os softwares fazem isso:

user do an action
       
       v
 application start processing action
   └──> loop ...
          └──> busy processing
 end loop
   └──> send result to user

No entanto, não é assim que aplicativos da Web, ou mesmo qualquer aplicativo com um banco de dados como back-end, funcionam. Os aplicativos da Web fazem isso:

user do an action
       
       v
 application start processing action
   └──> make database request
          └──> do nothing until request completes
 request complete
   └──> send result to user

Nesse cenário, o software passa a maior parte de seu tempo de execução usando 0% de tempo de CPU aguardando o retorno do banco de dados.

Aplicativo de rede multithread:

Os aplicativos de rede multithread lidam com a carga de trabalho acima da seguinte maneira:

request ──> spawn thread
              └──> wait for database request
                     └──> answer request
request ──> spawn thread
              └──> wait for database request
                     └──> answer request
request ──> spawn thread
              └──> wait for database request
                     └──> answer request

Portanto, o encadeamento passa a maior parte do tempo usando 0% da CPU aguardando o retorno do banco de dados. Ao fazer isso, eles tiveram que alocar a memória necessária para um encadeamento que inclui uma pilha de programas completamente separada para cada encadeamento etc. Além disso, eles teriam que iniciar um encadeamento que, embora não seja tão caro quanto iniciar um processo completo, ainda não é exatamente barato.

Loop de evento com leitura única

Como passamos a maior parte do tempo usando 0% da CPU, por que não executar algum código quando não estamos usando a CPU? Dessa forma, cada solicitação ainda terá o mesmo tempo de CPU que os aplicativos multithread, mas não precisamos iniciar um encadeamento. Então fazemos isso:

request ──> make database request
request ──> make database request
request ──> make database request
database request complete ──> send response
database request complete ──> send response
database request complete ──> send response

Na prática, ambas as abordagens retornam dados com aproximadamente a mesma latência, já que é o tempo de resposta do banco de dados que domina o processamento.

A principal vantagem aqui é que não precisamos gerar um novo encadeamento, portanto não precisamos fazer muito e muito malloc, o que nos atrasaria.

Rosca mágica, invisível

A coisa aparentemente misteriosa é como as duas abordagens acima conseguem executar a carga de trabalho em "paralelo"? A resposta é que o banco de dados é encadeado. Portanto, nosso aplicativo de thread único está realmente aproveitando o comportamento multithread de outro processo: o banco de dados.

Onde a abordagem de falha única falha

Um aplicativo de leitura única falha muito se você precisar fazer muitos cálculos de CPU antes de retornar os dados. Agora, não quero dizer um loop for processando o resultado do banco de dados. Isso ainda é principalmente O (n). O que quero dizer é fazer transformações de Fourier (codificação mp3, por exemplo), traçado de raios (renderização em 3D) etc.

Outra armadilha dos aplicativos de leitura única é que ele utilizará apenas um único núcleo da CPU. Portanto, se você possui um servidor quad-core (hoje em dia não é incomum), não está usando os outros três núcleos.

Onde a abordagem multithread falha

Um aplicativo multithread falha muito se você precisar alocar muita RAM por thread. Primeiro, o uso da RAM significa que você não pode lidar com tantas solicitações quanto um aplicativo com um único filtro. Pior, malloc é lento. Alocar muitos e muitos objetos (o que é comum em estruturas modernas da Web) significa que podemos acabar sendo mais lentos que os aplicativos com um único filtro. É aqui que o node.js geralmente vence.

Um caso de uso que acaba piorando os multithread é quando você precisa executar outra linguagem de script em seu encadeamento. Primeiro, você geralmente precisa centralizar todo o tempo de execução para esse idioma, depois precisa centralizar as variáveis ​​usadas pelo seu script.

Portanto, se você estiver escrevendo aplicativos de rede em C ou em go ou java, a sobrecarga do encadeamento geralmente não será muito ruim. Se você estiver escrevendo um servidor Web C para servir PHP ou Ruby, é muito fácil escrever um servidor mais rápido em javascript ou Ruby ou Python.

Abordagem híbrida

Alguns servidores da web usam uma abordagem híbrida. Nginx e Apache2, por exemplo, implementam seu código de processamento de rede como um pool de threads de loops de eventos. Cada encadeamento executa um loop de eventos simultaneamente processando solicitações de encadeamento único, mas os pedidos são balanceados por carga entre vários encadeamentos.

Algumas arquiteturas de thread único também usam uma abordagem híbrida. Em vez de ativar vários encadeamentos a partir de um único processo, você pode iniciar vários aplicativos - por exemplo, 4 servidores node.js. em uma máquina quad-core. Em seguida, você usa um balanceador de carga para distribuir a carga de trabalho entre os processos.

Com efeito, as duas abordagens são imagens espelhadas tecnicamente idênticas uma da outra.


Etapas de processamento do modelo de loop de evento com thread único:

  • Clientes enviam solicitação ao servidor Web.

  • O nó JS Web Server mantém internamente um pool de Threads limitados para fornecer serviços às Solicitações de Cliente.

  • O nó JS Web Server recebe esses pedidos e os coloca em uma fila. É conhecido como "Fila de eventos".

  • O nó JS Web Server internamente possui um componente, conhecido como "Event Loop". A razão pela qual recebeu esse nome é que ele usa um loop indefinido para receber solicitações e processá-las.

  • O Loop de Eventos usa apenas um thread único. É o coração principal do Node JS Platform Processing Model.

  • O loop uniforme verifica se qualquer solicitação de cliente é colocada na fila de eventos. Se não, aguarde solicitações recebidas indefinidamente.

  • Se sim, escolha uma solicitação de cliente na fila de eventos

    1. Inicia o processo que a solicitação do cliente
    2. Se essa solicitação do cliente não exigir nenhuma operação de bloqueio de E / S, processe tudo, prepare a resposta e envie-a de volta ao cliente.
    3. Se essa solicitação de cliente exigir algumas operações de bloqueio de E / S, como interagir com banco de dados, sistema de arquivos e serviços externos, ela seguirá uma abordagem diferente
  • Verifica a disponibilidade de Threads no Pool de Threads Internos

  • Pega um segmento e atribui essa solicitação de cliente a esse segmento.
  • Esse segmento é responsável por atender a essa solicitação, processá-la, executar operações de bloqueio de E / S, preparar a resposta e enviá-la de volta ao loop de eventos

    muito bem explicado por @Rambabu Posa para mais explicações vá jogar este Link





node.js