java design-patterns asynchronous nio asyncsocket

Java IO no bloqueante y asíncrono con NIO y NIO.2(JSR203)-Implementaciones de Reactor/Proactor



design-patterns asynchronous (4)

Así que aquí estoy leyendo uno de mis libros de patrones de software favoritos (Arquitectura de software orientada a patrones - Patrones para objetos concurrentes y en red), específicamente las secciones sobre patrones de I / O asíncrono Proactor / Reactor. Puedo ver cómo al usar canales seleccionables puedo implementar un mecanismo IO asíncrono estilo Reactor bastante fácil (y lo he hecho). Pero no veo cómo implementaría un mecanismo Proactor adecuado con escrituras sin bloqueo. Eso es aprovechar las funciones de escritura sin bloqueo gestionadas por el SO.

Funcionalidad soportada por llamadas específicas del sistema operativo como GetQueuedCompletionStatus en win32.

Vi que Java 7 trae algunas actualizaciones a NIO con controladores de finalización asíncronos (que parece estar en la dirección correcta). Dicho esto ... Dada la falta de compatibilidad multiplataforma unificada para las operaciones asíncronas administradas por SO (específicamente la escritura asíncrona), estoy asumiendo que se trata de una implementación de quassy que no utiliza soporte de sistema operativo nativo.

Así que mis preguntas son, es posible el manejo de IO basado en proactor en Java de tal manera que es ventajoso usarlo para escenarios específicos; y, si Java NIO admite el manejo de IO basado en proactor (ya sea en Java 6 o Java 7), ¿se está utilizando el soporte de IO asíncrono gestionado por el sistema operativo (es decir, devoluciones de llamada de finalización del sistema operativo)? Además, si la implementación es puramente en VM, el rendimiento es tan pequeño que el manejo proactivo de eventos no ofrece más que una forma diferente (posiblemente más simple) de construir un software de manejo de red concurrente.

Para cualquier persona interesada en el manejo proactivo de eventos, aquí hay un buen artículo que describe los pros / contras y una comparación tanto con los tradicionales hilos por conexión como con los modelos reactivos de IO.


uno de mis libros de patrones de software favoritos (Arquitectura de software orientada a patrones - Patrones para objetos concurrentes y en red)

Con respecto a ese libro, está muy desactualizado y es de dudosa relevancia en cualquier fecha. Salió del frenesí de los patrones de diseño de finales de la década de 1990, cuando hubo un intento concertado de reducir la totalidad de la informática a los patrones de diseño.

Mi opinión actual es que NIO ya es un marco y un patrón de diseño.


Hay muchos factores involucrados en esto. Trataré de resumir mis hallazgos de la mejor manera posible (consciente del hecho de que existe una controversia con respecto a la utilidad de las implementaciones de manejo de IO de reactores y procesadores).

Es posible el manejo de IO basado en proactor en Java de tal manera que es ventajoso usarlo para escenarios específicos.

Java 1.4 introdujo IO no bloqueante que NO es lo mismo que IO asincrónico. Java SE 7 introduce IO asíncrona con JSR203, lo que hace posibles las implementaciones de manejo de IO de estilo proactor "verdadero".

Ver AsyncrhonousSocketChannel , AsynchronousServerSocketChannel

y, si Java NIO admite el manejo de IO basado en proactor (ya sea en Java 6 o Java 7), ¿se está utilizando el soporte de IO asíncrono gestionado por el sistema operativo (es decir, devoluciones de llamada de finalización del sistema operativo)?

Al leer las especificaciones de JSR 203, los manejadores de finalización que usan canales asíncronos nuevos son definitivamente compatibles y se informa que se están utilizando las características nativas del sistema operativo, pero aún no sé en qué medida. Puedo hacer un seguimiento de esto después de un análisis de la fuente de Java 7 (a menos que alguien me gane).

Además, si la implementación es puramente en VM, el rendimiento es tan pequeño que el manejo proactivo de eventos no ofrece más que una forma diferente (posiblemente más simple) de construir un software de manejo de red concurrente.

No he podido encontrar ninguna comparación de rendimiento con respecto a las nuevas funciones Asynchronous IO en Java 7. Estoy seguro de que estarán disponibles en un futuro próximo.

Como siempre, cuando se le presentan más de una manera de abordar un problema, las preguntas sobre qué enfoque es mejor casi siempre se responden con "depende". El manejo proactivo de eventos (usando manejadores de terminación asíncronos) se incluye con Java 7 y no puede existir simplemente sin propósito. Para ciertas aplicaciones, tendrá sentido usar dicho manejo IO. Históricamente, un ejemplo común dado que proactor tiene buena aplicabilidad es en un servidor HTTP donde muchas solicitudes cortas se emiten con frecuencia. Para una explicación más profunda, dé una lectura (proporcionada únicamente para resaltar las ventajas de proactor, así que trate de pasar por alto el hecho de que el código de ejemplo es C ++).

OMI parece obvio que en muchas circunstancias reactor / proactor complica lo que de otra manera sería un diseño muy simple utilizando un enfoque más tradicional y en otros sistemas más complejos ofrecen un alto grado de simplificación y flexibilidad.

. . .

En una nota lateral, recomiendo leer la siguiente presentación sobre NIO, que ofrece una comparación de rendimiento entre NIO y el enfoque "tradicional". Aunque también aconsejaría precaución con respecto a los resultados presentados ya que la implementación de NIO en el benchmark se basó en la biblioteca pre Java 1.4 NBIO NIO y no en la implementación de NIO incluida en 1.4.


Verificaría que realmente necesita preocuparse por bloquear las escrituras.

A bloques leídos donde no hay datos para leer. Esto puede ser la mayor parte del tiempo. Sin embargo, los bloques de escritura cuando los almacenamientos intermedios están llenos, esto ocurre muy raramente y a menudo indica una conexión lenta o un consumidor fallido.

Si desea IO no bloqueante, hágalo para las lecturas y, por lo tanto, también para las escrituras.

Nota: El uso de IO de bloqueo con NIO suele ser más simple y puede realizar NIO sin bloqueo a menos que tenga miles de conexiones, es probable que descubra que la complejidad añadida no lo vale. (Y posiblemente no sea la mejor opción)


NIO ya proporciona una implementación del patrón reactivo (selectores) y NIO2 agrega una implementación del patrón proactivo (controladores de finalización).

No lo reinvente, simplemente úselo, porque no puede vencer su rendimiento, que es lo que cualquiera que intente evitar el bloqueo de E / S busca después de todo, con una solución pura de Java, ya que no tiene acceso al no- funciones de bloqueo / asincrónicas del sistema operativo subyacente. Pero NIO y NIO2 hacen uso de esos, lo que los hace rápidos.