netty-channel篇

作者: leiwingqueen | 来源:发表于2019-07-01 23:30 被阅读0次

    一、概要

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

    二、channel是什么?

    channel.png

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

    • channelHandler
    • channelHandlerContext
    • channelPipeline

    三、ChannelHandlerContext

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

    • 维护ChannelHandler的一些状态信息的存储
    • ChannelHandler之间互相通讯的桥梁(通过ChannelHandlerContext,我们可以把上一个ChannelHandler的处理结果传递给下一个ChannelHandler )


      ChannelHandlerContext类图

    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组成的核心组件有哪些,后面再对每一个组件做一一分析。

    相关文章

      网友评论

        本文标题:netty-channel篇

        本文链接:https://www.haomeiwen.com/subject/soybcctx.html