Por que o Node.js é encadeado único? [fechadas]


255

Nos servidores Web baseados em PHP (ou Java / ASP.NET / Ruby), toda solicitação de cliente é instanciada em um novo encadeamento. Mas no Node.js todos os clientes são executados no mesmo thread (eles podem até compartilhar as mesmas variáveis!) Eu entendo que as operações de E / S são baseadas em eventos, para que não bloqueiem o loop principal do thread.

O que não entendo é POR QUE o autor do Node o escolheu como single-thread? Isso dificulta as coisas. Por exemplo, não consigo executar uma função intensiva da CPU porque ela bloqueia o encadeamento principal (e as novas solicitações do cliente são bloqueadas), por isso preciso gerar um processo (o que significa que preciso criar um arquivo JavaScript separado e executar outro processo de nó no isto). No entanto, no PHP, as tarefas intensivas da CPU não bloqueiam outros clientes porque, como mencionei, cada cliente está em um segmento diferente. Quais são as suas vantagens em comparação com servidores Web multiencadeados?

Nota: usei o clustering para contornar isso, mas não é bonito.


12
Recentemente, assisti a um bom vídeo (29 minutos) explicando algumas das teorias por trás do Node. Eu até acho que as conversas cara sobre tarefas da CPU intensiva e brevemente como lidar com eles: youtube.com/watch?v=L0pjVcIsU6A
whirlwin

24
Você pode saber disso, mas para deixar claro, o Node.js não é de thread único. Seu código JavaScript executa thread único, mas as operações de E / S e outras coisas que os plug-ins podem executar ficam sem um pool de threads. O Node.js oferece muitos dos benefícios do multithreading sem precisar lidar com o código multithread. Além disso, os colaboradores do Node.js. não escolheram a natureza do JavaScript de thread único, os autores do JavaScript. Não consigo pensar em como o JS poderia funcionar em um contexto multithread, mas mesmo que houvesse, o V8 não é escrito dessa maneira, que é o que o Node.js usa como mecanismo de JavaScript.
Brad

5
PHP é mais thread único que JavaScript. Você provavelmente está pensando em módulos de servidor como FastCGI ou mod_php. Então, na verdade, você está comparando o Node.js ao Apache, Nginx ou IIS - não ao PHP, Java ou Ruby.
Álvaro González

34
O nó não é de thread único. É um equívoco popular. Mesmo simples node -e 'setTimeout(()=>{},1000);' & ps -T h $! | wc -l; kill $!exibe cinco threads no meu sistema. O loop do evento principal é de thread único (não faria muito sentido se não fosse), mas o Node é altamente multi-thread e você pode escrever aplicativos de processo único multi-thread, se desejar. Eu adoraria escrever uma resposta abrangente sobre isso, mas algumas pessoas decidiram encerrar sua pergunta, então não posso. Estou votando para reabri-lo. Se conseguir mais votos e reabrir, mencione-me no comentário.
Rsp 03/02

2
@rsp obrigado pelo seu comentário, mas eu quis dizer no tópico principal não relacionado à E / S. se você estiver fazendo algo relacionado à CPU, como um loop for grande que faz alguma coisa, o servidor para de processar as conexões. ou seja, o servidor não pode ser usado no momento. por isso, deixamos de usar hacks como clusters apenas para fazer algo tão simples, em vez de inerentemente segmentar todas as conexões como a maioria dos servidores. O jxcore.com tentou resolver isso, mas depois usa plugins de nó especiais / modificados, o que basicamente o torna inutilizável para mim.
Foreyez #

Respostas:


292

O Node.js foi criado explicitamente como um experimento no processamento assíncrono. A teoria era que o processamento assíncrono em um único encadeamento poderia fornecer mais desempenho e escalabilidade sob cargas típicas da Web do que na implementação típica baseada em encadeamento.

E sabe de uma coisa? Na minha opinião, essa teoria foi confirmada. Um aplicativo node.js que não está executando muitas tarefas de CPU pode executar milhares de conexões simultâneas a mais do que Apache, IIS ou outros servidores baseados em encadeamento.

A natureza única, assíncrona e encadeada dificulta as coisas. Mas você honestamente acha que é mais complicado do que enfiar? Uma condição de corrida pode arruinar seu mês inteiro! Ou esvazie seu pool de threads devido a alguma configuração em algum lugar e observe o tempo de resposta lento para um rastreamento! Sem mencionar impasses, inversões de prioridade e todas as outras rotações que acompanham o multithreading.

No final, não acho que seja universalmente melhor ou pior; é diferente, e às vezes é melhor e às vezes não é. Use a ferramenta certa para o trabalho.


26
Porém, os servidores da Web geralmente fazem MUITAS coisas intensivas na CPU, que não são APENAS busca de banco de dados. Precisamos processar o que buscamos e executar bastante lógica de negócios muitas vezes antes de atendê-la ao cliente.
foreyez 31/07

22
Então, basta gerar trabalhadores, bem! Esse é o negócio todo com o Node.js. Coisas pesadas podem ser executadas em outro processo, e você processa seus resultados em um retorno de chamada leve.
MaiaVictor 31/07

7
O problema é que há um processo no nível do sistema operacional em execução por trabalhador. Você os verá usando o comando "ps". Então, isso significa potencialmente milhares de processos em execução na máquina ao mesmo tempo - isso é loucura!
foreyez 31/07

9
@foreyez, você não precisa de um processo por usuário. Você pode escolher como dividir a carga. Além disso, nem todo mundo está fazendo uma tonelada de coisas intensivas na CPU. O nó é uma ferramenta para um trabalho ... talvez não seja o seu trabalho, mas muitos tipos de trabalho.
Brad

15
Na verdade, eu gostaria que o @foreyez fizesse backup dessa afirmação de que "os servidores da web geralmente usam MUITO (sic) itens de uso intensivo da CPU". Na minha experiência, eles não. Ou talvez minha definição de 'intensivo da CPU' seja diferente da dele. A conversão de dados do produto em uma interface do usuário não exige muita CPU nem calcula pedidos ou similares. A maior parte da web é bastante transacional. Os itens intensivos da CPU são coisas como converter vídeos, converter formatos de imagem, etc. Muito disso se deve à E / S de arquivo, que, na verdade, o nó faz muito bem. E facilita o descarregamento para outro processo dedicado à conversão.
Paulo

62

O problema com o modelo "um encadeamento por solicitação" para um servidor é que eles não escalam bem para vários cenários em comparação com o modelo de encadeamento de loop de eventos.

Normalmente, em cenários intensivos de E / S, as solicitações passam a maior parte do tempo aguardando a conclusão da E / S. Durante esse período, no modelo "um encadeamento por solicitação", os recursos vinculados ao encadeamento (como memória) não são utilizados e a memória é o fator limitante. No modelo de loop de eventos, o encadeamento de loop seleciona o próximo evento (E / S concluído) a ser manipulado. Portanto, o segmento está sempre ocupado (se você programá-lo corretamente, é claro).

O modelo de loop de eventos, como todas as coisas novas, parece brilhante e a solução para todos os problemas, mas qual modelo usar dependerá do cenário que você precisa enfrentar. Se você tiver um cenário intensivo de E / S (como um proxy), o modelo de base de eventos prevalecerá, enquanto um cenário intensivo de CPU com um número baixo de processos simultâneos funcionará melhor com o modelo baseado em encadeamento.

No mundo real, a maioria dos cenários fica um pouco no meio. Você precisará equilibrar a necessidade real de escalabilidade com a complexidade do desenvolvimento para encontrar a arquitetura correta (por exemplo, ter um front-end com base em eventos que delegue ao back-end para as tarefas intensivas da CPU. O front-end usará poucos recursos aguardando a tarefa Como em qualquer sistema distribuído, é necessário algum esforço para fazê-lo funcionar.

Se você estiver procurando pela bala de prata que se encaixa em qualquer cenário sem nenhum esforço, você terminará com uma bala no pé.


8
O Node.js está restrito ao processamento somente de eventos devido à falta de suporte a multithreading da v8. Bem, a própria linguagem javascript não possui os recursos necessários, portanto qualquer implementação acabará sendo complicada. Esse é o principal culpado do Node.js, na minha opinião. Em outros idiomas, você pode escolher o que deseja. Ou algum híbrido de ambos os modelos, como o Java NIO.
FrameGrace

2
@Kazaag, servidores web modernos fazem manter um pool de threads. Eles não geram apenas um novo thread por carregamento de página. Esses são os servidores web mais antigos.
Pacerier 19/02

1
@Pacerier Eu nunca disse que um novo thread é gerado, mas cada thread é alocado para uma solicitação até que ela seja concluída.
Kazaag

2
@ Kazaag Definitivamente, não é uma regra geral que "cada thread seja alocado a uma solicitação até que a solicitação seja concluída". Ou seja, no .Net (incluindo o processamento de solicitações HTTP), é possível e deve-se usar a programação assíncrona (baseada em tarefas) e isso liberará threads enquanto aguarda a conclusão de operações de E / S e outras operações assíncronas. Isso também é aplicável à programação de alto nível, ou seja, controladores MVC / API. Portanto, na prática, poderia haver 20 solicitações HTTP pendentes, mas apenas um encadeamento ativo.
usar o seguinte comando

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.