Notas del modo Reactor Java (giro) "IO escalable en Java"

  El modo Reactor es el modo IO utilizado por la mayoría de los componentes relacionados con IO como Netty y Redis. ¿Por qué se requiere este modo y cómo está diseñado para resolver la concurrencia de alto rendimiento?

La idea de programación de red más original es que el servidor utiliza un bucle while para monitorear continuamente el puerto en busca de nuevas conexiones de socket. Si es así, llama a una función de procesamiento para procesar, similar a:
while (true) {
socket = accept ();
handle (socket)
}
El mayor problema de este método es que no puede ser concurrencia y la eficiencia es demasiado baja. Si la solicitud actual no se procesa, la solicitud posterior solo se puede bloquear y el rendimiento del servidor es demasiado bajo.
Después de eso, pensé en usar subprocesos múltiples, que es una conexión clásica por subproceso. Cada conexión es manejada por un subproceso, similar a:
while (true) {
socket = accept ();
new thread (socket);
}
La versión anterior del servidor tomcat Este es de hecho el caso. El enfoque de subprocesos múltiples mejora en gran medida el rendimiento del servidor hasta cierto punto, porque la solicitud anterior no afectará las solicitudes posteriores después de que se bloquee la lectura, ya que están en subprocesos diferentes. Es por eso que generalmente se dice que "un hilo solo puede corresponder a un socket". Al principio no entendí esta oración. ¿No sería posible crear múltiples sockets en un hilo? De hecho, es gramaticalmente aceptable, pero en realidad es inútil. Cada socket está bloqueado, por lo que solo se puede procesar un socket en un hilo. Incluso si acepta múltiples sockets, el socket anterior está bloqueado, y el último es imposible. Fue ejecutado
La desventaja es que los requisitos de recursos son demasiado altos. La creación de subprocesos en el sistema requiere recursos del sistema relativamente altos. Si el número de conexiones es demasiado alto, el sistema no puede soportarlo, y la creación y destrucción repetidas de subprocesos también requiere un precio.
El grupo de subprocesos en sí mismo puede aliviar el costo de la creación-destrucción de subprocesos. Esta optimización es realmente mucho mejor, pero todavía hay algunos problemas, es decir, la granularidad del subproceso es demasiado grande. Cada hilo ha realizado todas las interacciones, incluida la lectura y el retorno, e incluso la conexión. En la superficie, parece que la conexión no está en el hilo, pero si el hilo no es suficiente, hay una nueva conexión y no se puede procesar. El hilo del programa se puede ver como tres cosas para hacer, conectarse, leer y escribir.
La granularidad de la sincronización de subprocesos es demasiado grande, lo que limita el rendimiento. El funcionamiento de una conexión debe dividirse en procesos o granularidades más finas, que son hilos más pequeños. El número de grupos de subprocesos completos se duplicará, pero los subprocesos son más simples y las tareas son más simples. Esta es la razón por la que aparece Reactor. En Reactor, estos pequeños subprocesos divididos o subprocesos corresponden a controladores, y cada controlador procesará un evento. Habrá un selector de administrador global, debemos registrar el canal para eventos de interés, luego este selector verificará continuamente si hay eventos de este tipo en el canal; de lo contrario, el hilo principal se bloqueará, de lo contrario Llamará a la función del controlador de eventos correspondiente para manejar. Los eventos típicos son conexión, lectura y escritura. Por supuesto, necesitamos proporcionar procesadores separados para estos eventos, y cada procesador puede implementarse por medio de hilos. Se produce una conexión, la pantalla es procesada por el hilo de lectura o el controlador, y luego se realiza la escritura, luego la lectura anterior puede ser reutilizada por la solicitud posterior, y se mejora el rendimiento.

[Java] Modo reactor

Casi todas las conexiones de red pasarán por el proceso de leer el contenido de la solicitud, "decodificación", procesamiento de cálculo, "respuesta de codificación", el proceso de evolución del modo Reactor es el siguiente:

En este modelo, IO siempre esperará cuando esté bloqueado, por lo que cuando aumenta la carga del usuario, el rendimiento cae muy rápidamente.

Causas del bloqueo del servidor:

1. El método de aceptación de serversocket bloquea la espera de la conexión del cliente hasta que la conexión del cliente sea exitosa.

2. Cuando el hilo lee datos del flujo de entrada del socket, entrará en un estado de bloqueo hasta que se lean todos los datos.

3. El hilo escribe datos en el flujo de salida del socket, que bloquea hasta que se escriben todos los datos.

 

Mejora: Al usar un diseño basado en eventos, cuando se dispara un evento, se llamará al procesador para el procesamiento de datos.

Reactor: responsable de responder a eventos IO. Cuando se detecta un nuevo evento, se envía al controlador correspondiente para su procesamiento.

Controlador: responsable de manejar el comportamiento sin bloqueo, identificando los recursos administrados por el sistema; al mismo tiempo, vincula el controlador al evento.

Reactor es un subproceso único que necesita manejar conexiones de aceptación y enviar solicitudes al procesador al mismo tiempo.

Debido a que solo hay un subproceso único, el negocio en el procesador debe procesarse rápidamente.

Mejora: Use múltiples hilos para procesar la lógica de negocios.

Coloque la ejecución del procesador en el grupo de subprocesos, multiproceso para el procesamiento empresarial. Pero Reactor sigue siendo un solo hilo.

Continuar mejorando: para máquinas con múltiples CPU, para aprovechar al máximo los recursos del sistema, Reactor se divide en dos partes.

Usando múltiples reactores

MainReactor es responsable de monitorear la conexión, y la conexión de aceptación es manejada por el subReactor ¿Por qué se debe usar un Reactor para manejar la supervisión? Debido a que se necesitan 3 apretones de manos para establecer una conexión como TCP, este proceso de establecimiento de conexión también requiere tiempo y recursos. Por separado, un Reactor para tratarlo puede mejorar el rendimiento.

Notas "IO escalable en Java"

 ¿Qué es el modo Reactor y cuáles son sus ventajas y desventajas?

Wikipedia dice: "El patrón de diseño del reactor es un patrón de manejo de eventos para manejar solicitudes de servicio entregadas simultáneamente por una o más entradas. El manejador de servicios luego demultiplexa las solicitudes entrantes y las envía sincrónicamente a los manejadores de solicitudes asociados". A partir de esta descripción, sabemos que el modo Reactor se controla primero por eventos, con una o más fuentes de entrada concurrentes, un controlador de servicio y múltiples controladores de solicitud ; este controlador de servicio multiplexará sincrónicamente la solicitud de entrada (evento) Distribución multiplexada al controlador de solicitud correspondiente. Si se expresa con un diagrama:

estructuralmente, esto es un poco similar al modelo de consumidor consumidor, es decir, uno o más productores ponen eventos en una Cola, y uno o más consumidores toman activamente eventos de Encuesta de esta Cola No hay cola para almacenar en búfer en el modo Reactor. Cuando se ingresa un evento en el controlador de servicio, el controlador de servicio lo distribuirá activamente al controlador de solicitud correspondiente para procesarlo según los diferentes tipos de eventos.

Estructura del patrón del reactor

Después de resolver qué es el patrón Reactor, echemos un vistazo a los módulos de los que está hecho el patrón Reactor. La imagen es una representación relativamente concisa de la imagen, por lo que la primera imagen para expresar el nombre de cada módulo y su relación:

Identificador: el identificador en el sistema operativo, es un tipo de recurso a nivel del sistema operativo Resumen, puede ser un archivo abierto, una conexión (Socket), Timer, etc. El modo Reactor se usa generalmente en la programación de red, por lo que aquí generalmente se refiere a Socket Handle, es decir, una conexión de red (Conexión, Canal en Java NIO). Este canal está registrado en el demultiplexor de eventos síncronos para monitorear los eventos que ocurren en el controlador.Puede ser un evento CONNECT para ServerSocketChannnel y READ, WRITE, CLOSE eventos para SocketChannel.
Desmultiplexor de eventos síncronos: bloqueo y espera de que lleguen una serie de eventos en el controlador. Si bloquea y espera el retorno, significa que el controlador devuelto puede ejecutar el tipo de evento devuelto sin bloquear. Este módulo generalmente se implementa utilizando la selección del sistema operativo. Está encapsulado con Selector en Java NIO. Cuando Selector.select () regresa, puede llamar al método selectedKeys () de Selector para obtener Set <SelectionKey>. Una SelectionKey expresa un canal con un evento y el tipo de evento en el canal. Si el flujo de "Demultiplexor de evento síncrono --- notifica-> Manejar" en la figura anterior es correcto, entonces la implementación interna debe ser que el método select () primero establecerá el estado del Manejador después de que llegue el evento, y luego regrese. No entiendo el mecanismo de implementación interno, por lo tanto, mantenga la imagen original.
Despachador de iniciación:Se usa para administrar Event Handler, el contenedor de EventHandler, para registrar y eliminar EventHandler, etc. Además, también sirve como la entrada del modo Reactor para llamar al método de selección de Sincrónico de eventos del demultiplexor para bloquear la espera de que el evento regrese. El controlador generado lo distribuye al controlador de eventos correspondiente para su procesamiento, es decir, devolver la llamada al método handle_event () en EventHandler. Controlador de
eventos: define el método de procesamiento de eventos: handle_event (), que utiliza la devolución de llamada InitiationDispatcher.
Concrete Event Handler: interfaz Event EventHandler para implementar lógica de procesamiento de eventos específica.

Modo de reactor detallado

Ventaja

1) Respuesta rápida, no necesita ser bloqueado por un solo tiempo de sincronización, aunque el Reactor mismo todavía está sincronizado;
2) La programación es relativamente simple, lo que puede evitar problemas complejos de subprocesamiento múltiple y sincronización en la mayor medida, y evitar la sobrecarga de conmutación de subprocesos múltiples / proceso ;
3) Escalabilidad, es conveniente hacer un uso completo de los recursos de la CPU aumentando el número de instancias del Reactor;
4) Reutilización, el marco del reactor en sí no tiene nada que ver con la lógica de procesamiento de eventos específicos y tiene una alta reutilización;
desventajas

1) En comparación con el modelo simple tradicional, Reactor agrega una cierta complejidad, por lo que tiene un cierto umbral y no es fácil de depurar.
2) El modo Reactor requiere el soporte subyacente del desmultiplexor de eventos síncronos, como el soporte del selector en Java y el soporte de llamada del sistema seleccionado del sistema operativo.Si desea implementar usted mismo el desmultiplexor de eventos síncronos, puede que no sea tan eficiente.
3) El modo Reactor se implementa en el mismo hilo al leer y escribir datos en IO. Incluso si se utilizan múltiples mecanismos de Reactor, si un Canal que comparte un Reactor tiene un largo período de lectura y escritura de datos, afectará al Reactor. El tiempo correspondiente de otros canales, como cuando se transfieren archivos grandes, las operaciones de E / S afectarán el tiempo correspondiente de otros clientes, por lo que para esta operación, el uso de Thread-Per-Connection tradicional puede ser una mejor opción, o luego Utiliza el modo Proactor.

Supongo que te gusta

Origin www.cnblogs.com/xingchong/p/12740006.html
Recomendado
Clasificación