Comprenda en 10 minutos el principio subyacente de Java NIO

Inserte la descripción de la imagen aquí

Escribir al frente

Muchos de mis amigos están un poco mareados por el modelo java IO, hay 4 modelos por un tiempo y 5 modelos por un tiempo.

Muchos socios pequeños también se confunden con el término nio. Durante un tiempo, nio de Java no se llama io sin bloqueo, y durante un tiempo, java nio es io sin bloqueo. ¿Qué es exactamente?

Muchos amigos se confunden por ser asincrónico y no bloqueante. Todo es sin bloqueo, ¿no es asincrónico?
Esto es tan dificil.

En este artículo, comenzando desde abajo, les daré a sus amigos, los cuatro principales modelos io de Java. Aquellos que necesitan una entrevista, o aquellos que no lo han descubierto, son completamente bendecidos.

1.1. Principio de lectura y escritura de Java IO

Ya sea lectura o escritura de Socket o lectura y escritura de archivos, desarrollo de aplicaciones a nivel Java o el desarrollo subyacente del sistema Linux, todos pertenecen al procesamiento de entrada y salida, conocido como lectura y escritura IO. Es consistente en principio y flujo de procesamiento. La diferencia radica en los diferentes parámetros.

Para que los programas de usuario lean y escriban E / S, se utilizan básicamente dos llamadas al sistema, lectura y escritura. Los diferentes sistemas operativos pueden tener diferentes nombres, pero las funciones son las mismas.

Primero enfatice un conocimiento básico: la llamada al sistema de lectura no es leer datos directamente desde el dispositivo físico a la memoria. La llamada al sistema de escritura no escribe datos directamente en el dispositivo físico.

La llamada al sistema de lectura es para copiar datos del búfer del núcleo al búfer del proceso; la llamada al sistema de escritura es para copiar datos del búfer del proceso al búfer del núcleo. Estas dos llamadas al sistema no son responsables del intercambio de datos entre el búfer del kernel y el disco. El intercambio de lectura y escritura subyacente lo completa el kernel del sistema operativo.

1.1.1. Búfer del núcleo y búfer de proceso

El propósito del búfer es reducir las frecuentes llamadas de E / S del sistema. Todo el mundo sabe que la llamada al sistema debe guardar los datos del proceso anterior y el estado y otra información, y después del final de la llamada, debe restaurar la información anterior. Para reducir esta llamada al sistema que consume tiempo y pérdida de rendimiento, por lo que aparece un búfer.

Con el búfer, el sistema operativo utiliza la función de lectura para copiar datos del búfer del núcleo al búfer del proceso, y la escritura copia los datos del búfer del proceso al búfer del núcleo. Espere a que el búfer alcance un determinado número y luego llame a IO para mejorar el rendimiento. El kernel decide cuándo leer y almacenar, y el programa de usuario no necesita preocuparse.

En el sistema Linux, el núcleo del sistema también tiene un búfer llamado búfer del núcleo. Cada proceso tiene su propio búfer independiente, llamado búfer de proceso.

Por lo tanto, el programa de lectura y escritura de E / S del programa de usuario, en la mayoría de los casos, no realiza la operación de E / S real, sino que lee y escribe su propio búfer de proceso.

1.1.2. El proceso subyacente de la lectura y escritura de Java IO

Los programas de usuario leen y escriben E / S, básicamente usan la llamada al sistema leer y escribir, leer copias de datos del búfer del núcleo al búfer del proceso, escribir copias de datos del búfer del proceso al búfer del kernel, no son equivalentes a los datos en Exchange entre el búfer del kernel y disco.

Inserte la descripción de la imagen aquí

Primero observe el proceso típico de una solicitud de red de procesamiento de servidor Java típica:

(1) Solicitud del cliente

Linux lee los datos de solicitud del cliente a través de la tarjeta de red y lee los datos en el búfer del kernel.

(2) Obtener datos de la solicitud

El servidor lee los datos del búfer del núcleo al búfer del proceso de Java.

(1) Procesamiento empresarial del lado del servidor

El servidor Java maneja las solicitudes de los clientes en su propio espacio de usuario.

(2) El servidor devuelve datos

La respuesta que ha creado el servidor Java se escribe desde el búfer del usuario en el búfer del sistema.

(3) Enviar al cliente

El kernel de Linux escribe los datos en el búfer del kernel en la tarjeta de red a través de la E / S de red, y la tarjeta de red envía los datos al cliente de destino a través del protocolo de comunicación subyacente.

1.2. Cuatro modelos principales de IO

La programación del lado del servidor a menudo requiere la construcción de modelos de E / S de alto rendimiento. Hay cuatro modelos de E / S comunes:

(1) IO de bloqueo síncrono (IO de bloqueo)

Primero, explique aquí el bloqueo y el no bloqueo:

El bloqueo de E / S se refiere a la necesidad de que las operaciones de E / S del kernel se completen por completo antes de volver al espacio del usuario para realizar las operaciones del usuario. El bloqueo se refiere al estado de ejecución del programa de espacio de usuario El programa de espacio de usuario debe esperar hasta que la operación IO se complete por completo. El modelo IO tradicional es IO de bloqueo síncrono. En Java, todos los sockets creados de forma predeterminada están bloqueando.

En segundo lugar, explique sincrónico y asincrónico :

La E / S sincrónica es una forma de iniciar llamadas entre el espacio del usuario y el espacio del kernel. IO síncrona significa que el subproceso del espacio de usuario es la parte que inicia activamente la solicitud de IO y el espacio del kernel es el destinatario pasivo. La E / S asincrónica, por otro lado, significa que el kernel del núcleo es la parte que inicia activamente las solicitudes de E / S, y el hilo del usuario es el destinatario pasivo.

(2) IO sin bloqueo síncrono (IO sin bloqueo)

IO sin bloqueo significa que el programa de usuario no necesita esperar a que se complete la operación de IO del kernel, y el kernel devuelve inmediatamente un valor de estado al usuario. El espacio de usuario no necesita esperar hasta que la operación de IO del kernel se complete por completo. . Puede volver inmediatamente al espacio de usuario para realizar la operación del usuario. Estado sin bloqueo.

En pocas palabras: bloquear significa que el espacio de usuario (subproceso de llamada) ha estado esperando y no hacer nada más; no bloquear significa que el espacio de usuario (subproceso de llamada) regresa cuando obtiene el estado, y la operación IO se puede realizar, no lo que sea puedes hacerlo, solo hazlo.

La E / S sin bloqueo requiere que el conector se establezca en NONBLOCK.

Para enfatizar, el modelo NIO (IO síncrono sin bloqueo) mencionado aquí no es la biblioteca NIO (New IO) de Java.

(3) Multiplexación de E / S (multiplexación de E / S)

Es decir, el patrón de diseño clásico de Reactor, a veces llamado IO de bloqueo asíncrono, es este modelo para Selector en Java y epoll en Linux.

(4) E / S asincrónica (E / S asincrónica)

E / S asíncrona se refiere a la inversa del método de llamada del espacio de usuario y el espacio del kernel. El hilo del espacio de usuario se acepta pasivamente y el espacio del núcleo es el llamador activo.

Esto es un poco similar al modo típico en Java es el modo de devolución de llamada.El hilo del espacio de usuario registra las funciones de devolución de llamada de varios eventos de IO en el espacio del kernel y es llamado activamente por el kernel.

1.3. Bloqueo IO síncrono (Blocking IO)

En el proceso de Java en Linux, todos los sockets bloquean la E / S de forma predeterminada. En el modelo de bloqueo de E / S, el programa de aplicación se bloquea desde el comienzo de la llamada al sistema de E / S hasta que regresa. Después de regresar con éxito, el proceso de solicitud comienza a procesar los datos almacenados en caché en el espacio de usuario.

Inserte la descripción de la imagen aquí

Por ejemplo, inicie una llamada de lectura del sistema operativo de un socket de bloqueo. El proceso es aproximadamente el siguiente:

(1) Cuando el hilo del usuario llama a la llamada al sistema de lectura, el kernel (kernel) comienza la primera etapa de IO: preparar datos. En muchos casos, los datos no han llegado al principio (por ejemplo, no se ha recibido un paquete de datos completo de Socket), en este momento el kernel tiene que esperar a que lleguen suficientes datos.

(2) Cuando el kernel espera hasta que los datos estén listos, copia los datos del búfer del kernel al búfer del usuario (memoria del usuario) y luego el kernel devuelve el resultado.

(3) Desde la llamada al sistema de lectura que inicia la lectura de E / S, el hilo del usuario entra en el estado de bloqueo. Después de que el kernel devuelve el resultado, el hilo del usuario libera el estado del bloque y comienza a ejecutarse nuevamente.

Por lo tanto, la característica de bloquear IO es que en las dos etapas de ejecución de IO en el kernel, los subprocesos de usuario están bloqueados.

Ventajas de BIO:

El programa es simple, el hilo del usuario se cuelga mientras está bloqueado esperando datos. Los hilos de usuario básicamente no ocupan recursos de la CPU.

Desventajas de BIO:

En circunstancias normales, se proporciona un subproceso independiente para cada conexión, o un subproceso mantiene la lectura y escritura de un flujo IO conectado correctamente. En el caso de una pequeña concurrencia, esto no es un problema. Sin embargo, en un escenario de alta concurrencia, se requiere una gran cantidad de subprocesos para mantener una gran cantidad de conexiones de red, y la sobrecarga de memoria y el cambio de subprocesos será muy grande. Por lo tanto, básicamente, el modelo BIO no está disponible en escenarios de alta concurrencia.

1.4. NIO sin bloqueo sincrónico (IO sin bloqueo)

En el sistema Linux, puede hacer que no se bloquee configurando el socket. En el modelo NIO, una vez que la aplicación inicia la llamada al sistema IO, ocurrirán las dos situaciones siguientes:

(1) Cuando no hay datos en el búfer del kernel, la llamada al sistema volverá inmediatamente y devolverá un mensaje de error de llamada.

(2) Cuando hay datos en el búfer del kernel, se bloquea hasta que los datos se copian del búfer del kernel al búfer de proceso del usuario. Una vez que se completa la copia, la llamada al sistema devuelve el éxito y el proceso de la aplicación comienza a procesar los datos almacenados en caché en el espacio del usuario.

Inserte la descripción de la imagen aquí

Regala una castaña. Inicie una llamada al sistema operativo de lectura de socket sin bloqueo, el proceso es así:

(1) Cuando los datos del kernel no están listos, cuando el hilo del usuario inicia una solicitud de E / S, regresa inmediatamente. Los subprocesos de usuario deben iniciar continuamente llamadas al sistema IO.

(2) Una vez que llegan los datos del kernel, el hilo del usuario inicia una llamada al sistema y el hilo del usuario se bloquea. El kernel comienza a copiar datos. Copiará los datos del búfer del núcleo del núcleo al búfer del usuario (memoria del usuario), y luego el núcleo devuelve el resultado.

(3) El hilo del usuario libera el estado del bloque y comienza a ejecutarse nuevamente. Después de muchos intentos, el hilo del usuario finalmente lee los datos y continúa la ejecución.

Características de NIO:

El subproceso de la aplicación debe realizar continuamente llamadas al sistema de E / S para sondear si los datos están listos. Si no están listos, continúe sondeando hasta que se complete la llamada al sistema.

Ventajas de NIO:

Cada llamada al sistema IO iniciada puede regresar inmediatamente mientras el kernel espera datos. Los hilos de usuario no se bloquearán y el rendimiento en tiempo real es mejor.

Desventajas de NIO:

Es necesario iniciar repetidamente llamadas al sistema IO. Este tipo de sondeo continuo consultará continuamente el kernel, lo que consumirá mucho tiempo de CPU y reducirá la utilización de recursos del sistema.

En resumen, el modelo NIO no está disponible en escenarios de alta concurrencia. Los servidores web generales no utilizan este modelo IO. Por lo general, este modelo rara vez se utiliza directamente, pero la E / S sin bloqueo se utiliza en otros modelos de E / S. En el desarrollo real de Java, este modelo de E / S no participará.

Una vez más, Java NIO (New IO) no es el modelo NIO en el modelo IO, sino otro modelo llamado multiplexación IO.

1.5. Modelo de multiplexación de E / S (multiplexación de E / S)

¿Cómo evitar el problema del sondeo y la espera en el modelo NIO sin bloqueo sincrónico? Este es el modelo de multiplexación IO.

El modelo de multiplexación de IO es a través de una nueva llamada al sistema, un proceso puede monitorear múltiples descriptores de archivos, una vez que un descriptor está listo (generalmente el búfer del kernel es legible / escribible), el kernel del kernel puede notificar al programa Realice la llamada al sistema IO correspondiente.

Actualmente admite llamadas al sistema de multiplexación IO, incluidas select, epoll, etc. La llamada al sistema selecto se admite actualmente en casi todos los sistemas operativos y tiene buenas características multiplataforma. Epoll fue propuesto en el kernel de Linux 2.6 y es una versión mejorada de Linux llamada select system.

El principio básico del modelo de multiplexación IO es la llamada al sistema select / epoll. Un solo hilo sondea continuamente cientos de miles de conexiones de socket que son responsables de la llamada al sistema select / epoll. Cuando llegan datos de una o algunas conexiones de red de socket, entonces Regrese a estas conexiones que se pueden leer y escribir. Por lo tanto, los beneficios son obvios: a través de una llamada al sistema select / epoll, se pueden consultar una o incluso cientos de conexiones de red que se pueden leer y escribir.

Regala una castaña. Inicie una llamada de sistema operativo de lectura de E / S multiplexada, el proceso es así:

Inserte la descripción de la imagen aquí

En este modo, el sistema de lectura no se moviliza primero, sino que se realiza la llamada al sistema select / epoll. Por supuesto, aquí hay una premisa: la red de destino debe estar conectada a la lista select / epoll de enchufes consultables de antemano. Luego, se puede iniciar el proceso de lectura de todo el modelo de multiplexación de E / S.

(1) Realice una llamada al sistema select / epoll para consultar las conexiones que se pueden leer. El kernel consultará la lista de sockets consultables para todas las selecciones, y cuando los datos en cualquier socket estén listos, la selección regresará.

Cuando el proceso de usuario llama a select, todo el hilo se bloqueará (bloqueará).

(2) Después de que el hilo del usuario obtiene la conexión de destino, inicia la llamada al sistema de lectura y el hilo del usuario se bloquea. El kernel comienza a copiar datos. Copiará los datos del búfer del núcleo del núcleo al búfer del usuario (memoria del usuario), y luego el núcleo devuelve el resultado.

(3) El hilo del usuario libera el estado del bloque y el hilo del usuario finalmente lee los datos y continúa la ejecución.

Características de IO multiplexado:

El modelo de multiplexación de E / S se basa en el sistema de separación de multiplexación llamada select / epoll que puede proporcionar el núcleo del sistema operativo. La multiplexación de E / S requiere dos llamadas al sistema, una para llamadas de consulta select / epoll y otra para llamadas de lectura de E / S.

Al igual que en el modelo NIO, la E / S multiplexada requiere sondeo. El hilo responsable de la llamada de consulta select / epoll necesita realizar continuamente el sondeo select / epoll para encontrar la conexión que puede realizar operaciones IO.

Además, el modelo IO multiplexado está relacionado con el modelo NIO anterior. Para cada socket que se puede consultar, generalmente se establece en un modelo sin bloqueo. Solo este punto es transparente (no perceptible) para el programa de usuario.

Ventajas de la E / S multiplexada:

La ventaja de usar select / epoll es que puede manejar miles de conexiones al mismo tiempo. En comparación con un hilo que mantiene una conexión, la mayor ventaja de la tecnología de multiplexación de E / S es que el sistema no necesita crear hilos o mantener estos hilos, lo que reduce en gran medida la sobrecarga del sistema.

La tecnología NIO (nueva IO) de Java utiliza el modelo de multiplexación IO. En el sistema Linux, se utiliza la llamada al sistema epoll.

Desventajas de la IO multiplexada:

Básicamente, la llamada al sistema select / epoll pertenece a IO síncrono y también a IO de bloqueo. Todos deben ser responsables de leer y escribir después de que el evento de lectura y escritura esté listo, lo que significa que el proceso de lectura y escritura está bloqueado.

¿Cómo desbloquear completamente el hilo? Ese es el modelo IO asincrónico.

1.6. Modelo IO asíncrono (IO asíncrono)

¿Cómo mejorar aún más la eficiencia y eliminar el último punto de obstrucción? Este es el modelo de E / S asíncrona, que significa E / S asíncrona, o AIO para abreviar.

El proceso básico de AIO es: el hilo del usuario le dice al kernel que inicie una determinada operación de IO a través de una llamada al sistema, y ​​el hilo del usuario regresa. Una vez que se completa toda la operación de E / S (incluida la preparación y copia de datos), el kernel del kernel notifica al programa del usuario y el usuario realiza las operaciones comerciales posteriores.

La preparación de datos del kernel es leer datos del dispositivo físico de la red (tarjeta de red) al búfer del kernel; la copia de datos del kernel es copiar los datos del búfer del kernel al búfer del espacio del programa del usuario.

Inserte la descripción de la imagen aquí

(1) Cuando el hilo del usuario llama a la llamada al sistema de lectura, puede comenzar inmediatamente a hacer otras cosas sin bloquear el hilo del usuario.

(2) El kernel (kernel) comienza la primera etapa de IO: preparar datos. Cuando el kernel espera hasta que los datos estén listos, copiará los datos del búfer del kernel al búfer del usuario (memoria del usuario).

(3) El kernel enviará una señal al hilo del usuario, o llamará a la interfaz de devolución de llamada registrada por el hilo del usuario para decirle al hilo del usuario que la operación de lectura está completa.

(4) El hilo del usuario lee los datos en el búfer del usuario y completa las operaciones comerciales posteriores.

Características del modelo IO asíncrono:

En las dos etapas del kernel de espera y copia de datos, el hilo del usuario no está bloqueado. El hilo del usuario debe aceptar el evento de la finalización de la operación IO del kernel, o registrar la función de devolución de llamada de la finalización de la operación IO en el kernel del sistema operativo. Por lo tanto, las E / S asíncronas a veces se denominan E / S controladas por señales.

Desventajas del modelo IO asíncrono:

Es necesario completar el registro y la entrega del evento, aquí el sistema operativo subyacente debe brindar mucho soporte y hacer mucho trabajo.

En la actualidad, la E / S asíncrona real se realiza a través de IOCP en el sistema Windows. Sin embargo, en lo que respecta a la industria actual, el sistema Windows rara vez se utiliza como sistema operativo de servidor con un millón o más de aplicaciones simultáneas.

Bajo Linux, el modelo de E / S asincrónico se introdujo solo en la versión 2.6, que actualmente no es perfecta. Por lo tanto, esto también ocurre en Linux, cuando se implementa la programación de red de alta concurrencia, el modelo de reutilización de IO es el modo principal.

Para resumir:

En los cuatro modelos IO, teóricamente, cuanto más tarde, menor es el bloqueo y la mejor eficiencia. Entre los cuatro modelos de E / S, los tres primeros son E / S síncronas, porque la operación de E / S real bloqueará el hilo. Solo el último es el modelo real de E / S asíncronas. Desafortunadamente, el sistema operativo Linux actual no es perfecto.

Supongo que te gusta

Origin blog.csdn.net/zzti_erlie/article/details/109302172
Recomendado
Clasificación