工作生活

netty-channel篇

2019-07-01  本文已影响0人  leiwingqueen

一、概要

上一篇把netty的基本思路介绍了一下,从这一篇文章开始我们将把netty的每一个组件分别进行拆解分析。针对核心的源码进行剖析。
本篇先重点分析下channel,netty的channel到底是一个什么样的概念。

二、channel是什么?

channel.png

channel代表的一个连接,每个client请求会对应到具体的一个channel。
我们可以看到channel对应有几个重要的组件。

三、ChannelHandlerContext

ChannelHandlerContext维护ChannelHandler的上下文内容。
什么是上下文?

DefaultChannelHandlerContext

final class DefaultChannelHandlerContext extends AbstractChannelHandlerContext {

    private final ChannelHandler handler;

    DefaultChannelHandlerContext(
            DefaultChannelPipeline pipeline, EventExecutor executor, String name, ChannelHandler handler) {
        super(pipeline, executor, name, handler.getClass());
        this.handler = handler;
    }

    @Override
    public ChannelHandler handler() {
        return handler;
    }
}

channelHandler是业务逻辑的核心处理类。
DefaultChannelHandlerContext会关联到一个唯一的ChannelHandler。

AbstractChannelHandlerContext

abstract class AbstractChannelHandlerContext implements ChannelHandlerContext, ResourceLeakHint {

    private static final InternalLogger logger = InternalLoggerFactory.getInstance(AbstractChannelHandlerContext.class);
    volatile AbstractChannelHandlerContext next;
    volatile AbstractChannelHandlerContext prev;

我只截取了部分代码,可以看到AbstractChannelHandlerContext维护了一个双向链表,分别指向前后的两个结点。
接下来我们看next和prev这两个指针(虽然不是指针,但是作用跟C的指针的类似的)其实是通过DefaultChannelPipeline来进行维护的。

DefaultChannelPipeline

DefaultChannelPipeline类图

pipeline,顾名思义就是channel的管道。Pipeline把channelHandler和Context给连接起来。

/**
 * The default {@link ChannelPipeline} implementation.  It is usually created
 * by a {@link Channel} implementation when the {@link Channel} is created.
 */
public class DefaultChannelPipeline implements ChannelPipeline {
...
...
//双向链表,维护了Context的首位指针
final AbstractChannelHandlerContext head;
    final AbstractChannelHandlerContext tail;
//关联一个对应的channel
private final Channel channel;
...
//把context添加到链表的尾部
private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;
    }
...
@Override
    public final ChannelPipeline addLast(EventExecutorGroup group, String name, ChannelHandler handler) {
        final AbstractChannelHandlerContext newCtx;
        synchronized (this) {
            checkMultiplicity(handler);

            newCtx = newContext(group, filterName(name, handler), handler);
//添加到尾部
            addLast0(newCtx);

            // If the registered is false it means that the channel was not registered on an eventLoop yet.
            // In this case we add the context to the pipeline and add a task that will call
            // ChannelHandler.handlerAdded(...) once the channel is registered.
            if (!registered) {
                newCtx.setAddPending();
                callHandlerCallbackLater(newCtx, true);
                return this;
            }

            EventExecutor executor = newCtx.executor();
            if (!executor.inEventLoop()) {
                callHandlerAddedInEventLoop(newCtx, executor);
                return this;
            }
        }
        callHandlerAdded0(newCtx);
        return this;
    }

我们可以看到ChannelPipeline通过Context把ChannelHandler给连接起来。并且在添加Handler的时候会触发ChannelHandler.handlerAdded的方法。

ChannelHandler

ChannelHandler 有多个不同的实现类,最顶层的接口就是这个。

public interface ChannelHandler {

    /**
     * Gets called after the {@link ChannelHandler} was added to the actual context and it's ready to handle events.
     */
    void handlerAdded(ChannelHandlerContext ctx) throws Exception;

    /**
     * Gets called after the {@link ChannelHandler} was removed from the actual context and it doesn't handle events
     * anymore.
     */
    void handlerRemoved(ChannelHandlerContext ctx) throws Exception;

    /**
     * Gets called if a {@link Throwable} was thrown.
     *
     * @deprecated if you want to handle this event you should implement {@link ChannelInboundHandler} and
     * implement the method there.
     */
    @Deprecated
    void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception;

    /**
     * Indicates that the same instance of the annotated {@link ChannelHandler}
     * can be added to one or more {@link ChannelPipeline}s multiple times
     * without a race condition.
     * <p>
     * If this annotation is not specified, you have to create a new handler
     * instance every time you add it to a pipeline because it has unshared
     * state such as member variables.
     * <p>
     * This annotation is provided for documentation purpose, just like
     * <a href="http://www.javaconcurrencyinpractice.com/annotations/doc/">the JCIP annotations</a>.
     */
    @Inherited
    @Documented
    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @interface Sharable {
        // no value
    }
}

四、总结

本篇主要分析了一个Channel组成的核心组件有哪些,后面再对每一个组件做一一分析。

上一篇下一篇

猜你喜欢

热点阅读