El procesamiento de los negocios: cómo difundir el evento está en la tubería

El procesamiento de los negocios: cómo difundir el evento está en la tubería

Netty catálogo de la serie ( https://www.cnblogs.com/binarylei/p/10117436.html )

Por una recepción de los datos: Adaptativo tampón de lectura y conexión para solucionar cualquier problema , sabemos que NioEventLoop constantemente sondeo, recibiendo evento OP_READ; a continuación, lea la difusión de datos a través de pipeline.fireChannelRead (byteBuf). Por lo que el proceso de negocio es, de hecho, channelRead procesamiento en paralelo en (), esta sección también se centra en los acontecimientos en la tubería está en el comportamiento de la comunicación.

En la tubería en la propagación de eventos, tenemos que centrarnos en el comportamiento de la comunicación y las discusiones de eventos de ejecución:

  1. comportamiento de la propagación: para realizar un post-Controlador de eventos, si no activar manualmente ctx.fireChannelRead, luego se extendió interrumpido.
  2. Hilo de ejecución: Hilo de negocios se ejecuta en NioEventLoop en default. Si hay una obstrucción de las necesidades de los procesos de negocio a ser considerada desde otro hilo.

1. Análisis de la línea principal

1.1 de largo recorrido

De hecho, en una línea principal se ha hablado, al leer los datos disparadores pipeline.fireChannelRead (byteBuf) para leer los datos distribuidos. Ahora tenemos centra en cómo los eventos se propagan en la tubería.

Manipulador de calificaciones de ejecución:

  • 实现 ChannelInboundHandler
  • channelRead implementación no anotado @Skip
  • cadena de ejecución Handler puede ser interrumpido. Si usted no toma la iniciativa con el método de disparo ctx.fireChannelRead no continuará por la aplicación.

1.2 puntos de conocimiento

(1) la naturaleza del proceso de negocio

ChannelInboundHandler channelRead todos los datos en la ejecución de tuberías (). Y la ejecución puede ser interrumpido.

(2) hilo de procesamiento de negocio

predeterminado de canal de procesamiento hilos están obligados hilo NioEventLoop, otros hilos también se pueden configurar:

pipeline.addLast(new UnorderedThreadPoolEventExecutor(10), serverHandler);

2. Análisis Fuente

2.1 propagación fireChannelRead en la tubería

@Override
public final ChannelPipeline fireChannelRead(Object msg) {
    AbstractChannelHandlerContext.invokeChannelRead(head, msg);
    return this;
}

Nota: se puede ver fireChannelRead de la cabeza -> Cola ha estado detrás de la propagación.

comportamiento 2,1 propagación

Una vez que la tubería se ejecuta en el medio de un manipulador, el comportamiento de la propagación se interrumpe. Si tiene que continuar la ejecución, tenemos que tomar la iniciativa de llamar ctx.fireChannelRead.

// AbstractChannelHandlerContext
@Override
public ChannelHandlerContext fireChannelRead(final Object msg) {
    invokeChannelRead(findContextInbound(MASK_CHANNEL_READ), msg);
    return this;
}

private void invokeChannelRead(Object msg) {
    if (invokeHandler()) {
        try {
            ((ChannelInboundHandler) handler()).channelRead(this, msg);
        } catch (Throwable t) {
            notifyHandlerException(t);
        }
    } else {
        fireChannelRead(msg);
    }
}

Nota: se puede ver ya sea llevar a cabo el método channelRead, o hasta que encuentre un método para llevar a cabo fireChannelRead correspondiente Handler hasta ahora. Si usted no llama al director ctx.fireChannelRead, el comportamiento de la propagación será interrumpida.

Puede preguntarse, correspondiente Handler por findContextInbound () no se encuentra, ¿por qué necesita a través invokeHandler juicio () una vez más? De hecho, tiene findContextInbound método channelRead es encontrar el controlador, y el método invokeHandler es determinar si el controlador ha sido eliminado.

2,3 hilo de ejecución

Cada Handler se ejecutan en su correspondiente ejecutor, el valor predeterminado es hilo NioEventLoop. Por supuesto, también puede especificar otros hilos usted mismo.

// AbstractChannelHandlerContext
static void invokeChannelRead(final AbstractChannelHandlerContext next, Object msg) {
    final Object m = next.pipeline.touch(ObjectUtil.checkNotNull(msg, "msg"), next);
    EventExecutor executor = next.executor();
    if (executor.inEventLoop()) {
        next.invokeChannelRead(m);
    } else {
        executor.execute(new Runnable() {
            @Override
            public void run() {
                next.invokeChannelRead(m);
            }
        });
    }
}

Descripción: Tenemos que centrarnos en hilos de ejecución de negocios, como si la ocupación de los negocios de producción tiempo es demasiado largo, que afectará a Netty IO.

2.4 ChannelPipeline vs ChannelHandlerContext

Netty cada Handler se empaquetan en ChannelHandlerContext añadido a ChannelPipeline en. A pesar de que ChannelPipeline método ChannelHandlerContext la llamada, pero la tubería comenzarán atraviesa la cabeza o la cola, y sólo empezarán a recorrer desde el lanzador CTX actual.

Todavía nos tomamos la siguiente comparación de cuatro lectura: channel.read (), pipeline.read (), ctx.read (), unsafe.read ()

  • channel.read (): pipeline.read Llamada directa ().
  • pipeline.read (): tail.read llamada (), todos experimentaron Manipulador de la cabeza o la cola. De hecho, la última head.read () llama a unsafe.beginRead (), este método registra OP_ACCEPT o OP_READ evento para activar el canal.
  • ctx.read (): todos CTX actual después Handler desde el principio. Si la transmisión de datos se requiere ctx.channel lugar ctx.write (). Escribir.
  • unsafe.read (): la parte inferior de la API. Y unsafe.beginRead () diferente, insegura # lectura realmente leer datos de la revbuf zócalo.

2.5 HeadContext vs TailContext

  • HeadContext:
    • entrante desencadenada por eventos, de la cabeza -> cola, por lo que es necesario llamar a eventos ctx.firexxx difundirlo.
    • saliente activado por el usuario, desde la cola -> cabeza, generalmente se llama directamente a la cabeza. Si el medio de una implementación personalizada re-Manejador del método, no va a cortar de nuevo, ver AbstractChannelHandlerContext # invokeWrite0.
  • TailContext: básicamente ninguna función, ha sido la propagación descendente de un evento puede ser.
función HeadContext
método orden de ejecución función
enlazar salientes unsafe.bind
conectar salientes unsafe.connect
desconectar salientes unsafe.disconnect
cerca salientes unsafe.close
Deregister salientes unsafe.deregister
leer salientes unsafe.beginRead: eventos de inscripción de interés
escribir salientes unsafe.write
rubor salientes unsafe.flush
exceptionCaught entrante ctx.fireExceptionCaught
channelRegistered entrante callHandlerAddedForAllHandlers
ctx.fireChannelRegistered
channelUnregistered entrante ctx.fireChannelUnregistered
destruir
channelActive entrante ctx.fireChannelActive
readIfIsAutoRead:调用unsafe.beginRead
channelInactive entrante ctx.fireChannelInactive ()
channelRead entrante ctx.fireChannelRead
channelReadComplete entrante ctx.fireChannelReadComplete
readIfIsAutoRead
userEventTriggered entrante ctx.fireUserEventTriggered
channelWritabilityChanged entrante ctx.fireChannelWritabilityChanged
función TailContext
método orden de ejecución función
channelRead entrante ReferenceCountUtil.release (msg)

Las intenciones de grabar un poco cada día. Tal vez el contenido no es importante, pero el hábito es muy importante!

Supongo que te gusta

Origin www.cnblogs.com/binarylei/p/12641011.html
Recomendado
Clasificación