91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

netty handler的執行順序是什么

發布時間:2021-12-16 16:46:21 來源:億速云 閱讀:295 作者:iii 欄目:云計算

這篇文章主要介紹“netty handler的執行順序是什么”,在日常操作中,相信很多人在netty handler的執行順序是什么問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”netty handler的執行順序是什么”的疑惑有所幫助!接下來,請跟著小編一起來學習吧!

handler的概念,讓我想到了其他的一些東西,就好像servlet當中的filter,spring當中的interceptor。 在handler當中,能夠完成各種各樣的工作,協議流的編解碼、特殊信息的攔截、請求數量的統計等等,或者可以這樣說,所有的業務層面的東西,都需要在handler當中來完成。

我會按照上行和下行兩類來分析handler的執行順序,今天先來下行的。

按照我最初的想象,所有的handler應該都是同一類東西,那么我們業務執行的方法,也就是我們繼承netty提供的父類之后,Override的方法,應該是同一個,可是我實際使用當中發現不是這么回事,有時候是一個decode方法,有時候是一個messageReceived方法,這是什么道理。基于這個困惑,才會有了今天的這篇文章。

首先是一個stacktrace的圖。

netty handler的執行順序是什么

ProtocolAnaDecoder是我自己寫的一個協議解析類,繼承自 ByteToMessageDecoder ,在這個類里面依次調用了3個方法,channelRead(),callDecode(),decode()。這其中decode,是我們自己實現的,其他2個方法來自父類。

再看另一個圖。

netty handler的執行順序是什么

NettyServerHandler繼承自SimpleChannelInboundHandler,這里依次調用了channelRead(),messageReceived()這樣2個方法。

到此為止基本就解決了我的第一個疑惑,最初都來自channelRead。那么這個 channelRead 雖然在各種handler當中都有實現,但是它的最初的定義來自ChannelHandler,這是一個interface。而它的實現ChannelHandlerAdapter,基本可以看做netty當中所有handler的老祖宗。(這里之所以要說基本,是因為有2個web相關的handler interface,直接繼承了 ChannelHandler,但這個不是我們今天討論的重點)

繼續,就該是ChannelHandlerInvokerUtil.invokeChannelReadNow,看代碼吧。

    public static void invokeChannelReadNow(final ChannelHandlerContext ctx, final Object msg) {
        try {
            ctx.handler().channelRead(ctx, msg);
        } catch (Throwable t) {
            notifyHandlerException(ctx, t);
        }
    }

清楚明白,很好理解。

然后是DefaultChannelHandlerInvoker.invokeChannelRead,代碼如下:

@Override
    public void invokeChannelRead(final ChannelHandlerContext ctx, final Object msg) {
        if (msg == null) {
            throw new NullPointerException("msg");
        }

        if (executor.inEventLoop()) {
            invokeChannelReadNow(ctx, msg);
        } else {
            safeExecuteInbound(new Runnable() {
                @Override
                public void run() {
                    invokeChannelReadNow(ctx, msg);
                }
            }, msg);
        }
    }

executor.inEventLoop() ,當前channel的 executor 是否處于時間循環當中,好吧,到目前為止,我也不知道什么時候會走到else里面去,這里只好留待以后再去搞搞清楚了。

再往前走,DefaultChannelHandlerContext.fireChannelRead,代碼如下:

public ChannelHandlerContext fireChannelRead(Object msg) {
        DefaultChannelHandlerContext next = findContextInbound(MASK_CHANNEL_READ);
        next.invoker.invokeChannelRead(next, msg);
        return this;
    }

handler的依次執行就在這里面體現了。

繼續,DefaultChannelPipeline.fireChannelRead,代碼如下:

public ChannelPipeline fireChannelRead(Object msg) {
        head.fireChannelRead(msg);
        return this;
    }

好了,如果沒記錯的話,我們最初聲明一個netty的時候,就是把一系列的handler加到了channel pipeline當中。那么這一系列的handler在pipeline當中是如何保存的呢。我首先先看一下 DefaultChannelPipeline 的構造函數:

public DefaultChannelPipeline(AbstractChannel channel) {
        if (channel == null) {
            throw new NullPointerException("channel");
        }
        this.channel = channel;

        TailHandler tailHandler = new TailHandler();
        tail = new DefaultChannelHandlerContext(this, null, generateName(tailHandler), tailHandler);

        HeadHandler headHandler = new HeadHandler(channel.unsafe());
        head = new DefaultChannelHandlerContext(this, null, generateName(headHandler), headHandler);

        head.next = tail;
        tail.prev = head;
    }

首先生命了一個tail和一個head,然后把這2個對象構成了一個雙向鏈表。

再看一下addlast方法:

private void addLast0(final String name, DefaultChannelHandlerContext newCtx) {
        checkMultiplicity(newCtx);

        DefaultChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;

        name2ctx.put(name, newCtx);

        callHandlerAdded(newCtx);
    }

很清楚,在鏈表當中插入一個元素。再對照一下前面的代碼,首先從head開始,但它并不完成實際工作,直接取它的next來執行,之后依次便利鏈表。

到此,關于“netty handler的執行順序是什么”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注億速云網站,小編會繼續努力為大家帶來更多實用的文章!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

营山县| 宁武县| 界首市| 乡宁县| 化德县| 阳高县| 安康市| 崇左市| 天全县| 聊城市| 阿拉善左旗| 嘉禾县| 绩溪县| 乌兰察布市| 元阳县| 无锡市| 延安市| 建湖县| 衡阳市| 中西区| 福安市| 益阳市| 剑川县| 鸡泽县| 靖安县| 泰安市| 通渭县| 和静县| 平谷区| 洛川县| 奇台县| 正安县| 安岳县| 江津市| 重庆市| 安陆市| 读书| 都江堰市| 璧山县| 错那县| 井研县|