Búsqueda de sitios web

javascript - ¿Cómo hace Nodejs la entrada/salida por debajo?


Sé que Node.js utiliza el grupo de subprocesos proporcionado por libuv para realizar trabajos concurrentes. Leí que Node.js solo necesita uno de esos subprocesos para realizar todas las actividades limitadas por I/O.

Entonces, ¿cómo ocurren las operaciones de archivo no bloqueantes?

¿Qué ocurrirá realmente bajo el capó entre el nodo, el disco y el sistema operativo, si recorro una carpeta que contiene 100 archivos y abro todos ellos usando readFile()?

Si hacer esta misma operación en algún otro lenguaje multihilo y bloqueante resultará en que los hilos esperen a que la entrada/salida termine, entonces ¿quién espera a que la entrada/salida termine en Node.js?, ¿especialmente cuando hay múltiples operaciones de archivos ocurriendo simultáneamente?

¡Gracias!

Respuesta #1

La E/S de archivos en Node.js utiliza un grupo de hilos. Por defecto, hay 4 hilos en el grupo.

Cuando algún código Javascript llama a una operación de archivo como fs.open() en nodejs, la llamada se enruta a un código nativo dentro de la biblioteca libuv en la implementación de nodejs. Ese código agrega la operación de archivo específica a una cola de elementos que esperan un hilo del sistema operativo. Si un hilo del sistema operativo está disponible de inmediato, entonces ese hilo del sistema operativo recibe la tarea de ejecutar la operación de archivo y luego la función original de libuv devuelve el control, lo que regresa al Javascript original y nodejs continúa ejecutando otro Javascript.

Luego, algún tiempo después, el hilo termina la operación de archivo y tiene un resultado. Inserta un evento en la cola de eventos de Node.js con el resultado completado y la devolución de llamada original pasada con la operación de archivo original.

Cuando Node.js ha terminado de ejecutar cualquier otro Javascript que estaba ejecutando, extrae el siguiente evento de la cola de eventos y llama a la función de devolución de llamada de Javascript asociada con ese evento y le pasa los datos asociados con el evento. Esto desencadena que se llame a la función de devolución de llamada de Javascript que originalmente se pasó a fs.open().

Si, en el segundo paso mencionado anteriormente, no hubiera hilos disponibles en el grupo de hilos, entonces la tarea se añade a una cola y libuv devuelve inmediatamente el control a nodejs para que pueda ejecutar otro Javascript. Más tarde, cuando uno de los hilos existentes en el grupo complete y termine su trabajo de añadir un evento a la cola de eventos, entonces tomará el siguiente elemento de la cola del grupo de hilos, le asignará el hilo ahora disponible y permitirá que comience a ejecutar su operación.

De esta manera, todas las operaciones de archivos parecen ser no bloqueantes y asíncronas desde el lado de Javascript. Se inician inmediatamente si hay un hilo disponible en el grupo de hilos o esperan en la cola del grupo de hilos hasta que un hilo esté disponible. Esa parte es invisible para el lado de Javascript. De cualquier manera, la operación se inicia o se pone en cola y el control regresa inmediatamente a nodejs para continuar ejecutando otros códigos de Javascript. Y, de cualquier manera, la operación se completa algún tiempo después y la función de devolución de llamada de Javascript asociada con la operación de archivo se llama a través de la cola de eventos de Javascript. Esto proporciona el mecanismo asíncrono, no bloqueante y basado en eventos que nodejs utiliza para todas las operaciones de entrada/salida de archivos.