Como o NodeJS pode ser "sem bloqueio"?

14

Estou aprendendo NodeJS e só queria esclarecer uma coisa. Até agora, em vários tutoriais e livros introdutórios, eles descreveram a arquitetura "sem bloqueio" do Node - ou melhor, é possível (e recomendado, o ponto inteiro) codificar de maneira não-bloqueadora.

Por exemplo, este exemplo foi fornecido em um livro que estou lendo de uma maneira assíncrona para obter dados de um banco de dados.

http.createServer(function (req, res) {
  database.getInformation(function (data) {
      res.writeHead(200);
      res.end(data);
  });
});

O que acontece (como eu o entendo) é que o Node faz a chamada para o banco de dados e continua processando o que quer que seja o próximo na pilha de chamadas. Quando a solicitação do banco de dados for concluída, a variável de dados na função de retorno de chamada anônima será preenchida e essa função adicionada à pilha de chamadas (e subsequentemente executada quando o Node chegar a ela).

Minha pergunta é: o que exatamente está processando a solicitação do banco de dados? Certamente o Node precisa bloquear enquanto faz isso? O que está cuidando da solicitação do banco de dados? Ou, se o Node estiver aguardando uma solicitação HTTP GET assíncrona para um recurso externo, o que está cuidando dessa solicitação que permite que o Node continue processando a pilha de chamadas e seja "sem bloqueio"?

Anônimo
fonte

Respostas:

17

Quando o Node.js é descrito como "sem bloqueio", isso significa especificamente que seu IO é sem bloqueio. O nó usa o libuv para lidar com suas E / S de uma maneira independente de plataforma. No Windows, ele usa portas de conclusão de E / S, no Unix, usa epoll / kqueue / select / etc. Portanto, ele faz uma solicitação de E / S sem bloqueio (que pode ter um monitoramento de encadeamento em segundo plano, mas isso nunca é exposto ao JavaScript) e, como resultado, enfileira-a no loop de eventos que chama o retorno de chamada do JavaScript no principal (leia-se: apenas) thread JavaScript.

Para bancos de dados, isso depende de como a biblioteca é gravada. Se ele usa HTTP para se comunicar (como fazem alguns bancos de dados NoSQL), ele pode ser facilmente escrito em JavaScript puro usando a httpbiblioteca de nós padrão . Se fizer de outra maneira, bem, isso depende da biblioteca. Pode ser escrito em C / C ++ e usar threads em segundo plano, desde que essa abstração nunca seja exposta ao JavaScript.

Quanto à sua pergunta sobre o que está "processando" a solicitação do banco de dados, idealmente, tudo o que deve ser feito é enviar uma mensagem simples para uma biblioteca (por exemplo, uma instrução SQL ou alguma outra consulta ou solicitação de conexão) e, nesse ponto, seu JavaScript continua chugging. Quando a biblioteca está pronta para enviar uma mensagem de volta, ela envia uma mensagem de volta para a fila de eventos do nó que executa o retorno de chamada, permitindo que esse trecho de código seja executado.

ckknight
fonte
Existe o netpacote quando o http não está disponível.
Florian Margaine
Detalhe que pode ajudar. O nó utiliza o mecanismo V8 JS. Um dos melhores recursos do V8 é a facilidade de vincular processos C / C ++ a chamadas JS. As funções JavaScript estão bloqueando, mas tudo o que uma função faz é chamar algo oculto que não bloqueia. Em seguida, outra função JS responde quando esse processo é concluído. As funções JS bloqueando uma à outra significa que você nunca terá duas coisas tentando fazer algo como agendar uma gravação no mesmo local do arquivo ao mesmo tempo, que é onde eu presumo que o multi-thread precisa ser gerenciado. É sempre claro qual solicitação veio primeiro com o objetivo de enfileirar as coisas.
Erik Reppen