亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

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

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

什么是Netty事件傳播

發布時間:2021-06-23 14:10:39 來源:億速云 閱讀:399 作者:chen 欄目:編程語言

本篇內容主要講解“什么是Netty事件傳播”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“什么是Netty事件傳播”吧!

Netty高性能的背后,蘊含著優秀的設計。 今天我們從源碼角度詳細介紹Netty中ChannelPipeline的事件,以及這些事件是如何在ChannelPipeline中傳播的。

ChannelPipeline

ChannelPipeline是負責管理ChannelHandler的有序容器。 其內部維護著一個由ChannelHandlerContext做為節點的雙向鏈表。 Netty上的事件便是通過這個鏈表進行傳播的。

一圖勝千言

什么是Netty事件傳播

ChannelPipeline需要注意以下幾個關鍵點:

  • Netty事件分為入站事件(inbound_event)和出站事件(outbound_event),入站事件由 InboundHandler 處理,出站事件由 OutboundHandler 處理

  • 事件通過ChannelHandlerContext進行傳播,入站事件順序傳播,出站事件逆序傳播

  • 事件是顯示觸發的。(handler處理事件后,若要傳遞給下一個handler,必須顯示調用ChannelHandlerContext里的方法)

其中, 入站事件包括:

  • firefireChannelRegistered

  • fireChannelUnregistered

  • fireChannelActive

  • fireChannelInactive

  • fireChannelRead

  • fireChannelReadComplete

  • fireUserEventTriggered

  • fireChannelWritabilityChanged

  • fireExceptionCaught

出站事件包括:

  • bind

  • connect

  • disconnect

  • close

  • deregister

  • read

  • write

  • flush

  • writeAndFlush

handler里可以觸發任意的事件,即在InboundHandler里可以觸發出站事件,而OutboundHandler里也可以觸發入站事件。但注意不要出現事件的死循環。

更進一步的,我們從源碼上去解讀ChannelPipeline的幾個要點:

  • ChannelPipeline實例化后便提供了一個頭節點和一個尾節點的雙向鏈表

    protected DefaultChannelPipeline(Channel channel) {
        this.channel = ObjectUtil.checkNotNull(channel, "channel");
        succeededFuture = new SucceededChannelFuture(channel, null);
        voidPromise =  new VoidChannelPromise(channel, true);

        tail = new TailContext(this);   //尾節點
        head = new HeadContext(this);   //頭節點

        // 通過前驅與后續引用,形成一個雙向鏈表
        head.next = tail;
        tail.prev = head;
    }
  • 頭節點被標記為outbound和inboud,尾節點標記為inboud。(在下面的ChannelHandlerContext會介紹其作用)

  • 頭節點的入站處理程序會觸發新的入站事件,出站處理程序會調用unsafe對象的操作(將數據輸出到Sokect)。

  • 尾節點的入站處理程序是空處理或回收資源操作,出站處理程序觸發新的出站事件。

    HeadContext(DefaultChannelPipeline pipeline) {
        super(pipeline, null, HEAD_NAME, true, true);   // outbound=true
        unsafe = pipeline.channel().unsafe();   // 出站事件傳播到了頭節點后,便調用該unsafe對象上的方法
        setAddComplete();
    }

    TailContext(DefaultChannelPipeline pipeline) {
        super(pipeline, null, TAIL_NAME, true, false);  // inboud=true
        setAddComplete();
    }

    protected void onUnhandledInboundMessage(Object msg) {
        try {
            logger.debug(
                    "Discarded inbound message {} that reached at the tail of the pipeline. " +
                            "Please check your pipeline configuration.", msg);
        } finally {
            ReferenceCountUtil.release(msg);    // 釋放引用,當引用為0時,便可回收內存空間
        }
    }

    protected void onUnhandledInboundChannelReadComplete() {    // 空處理
    }

    @Override
    public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
        unsafe.write(msg, promise);     // 通過unsafe將數據輸出
    }
  • 在Channel和ChannelPineline上的事件會傳遞給頭節點(入站)或尾節點(出站)。(再配合其他節點的handler,就可以形成了從頭到尾(或從尾到頭)依次傳播的事件)

    @Override
    public final ChannelPipeline fireChannelActive() {
        AbstractChannelHandlerContext.invokeChannelActive(head); //觸發head節點入站事件
        return this;
    }

    @Override
    public final ChannelFuture writeAndFlush(Object msg) {
        return tail.writeAndFlush(msg); // 觸發tail節點出站事件
    }
  • addXXX(ChannelHandler)會實例化一個含handler的ChannelHandlerContext對象,并插入鏈表。

  • addFirst在頭節點后插入新節點,addLass在尾節點前插入新節點。

private AbstractChannelHandlerContext newContext(EventExecutorGroup group, String name, ChannelHandler handler) {
        return new DefaultChannelHandlerContext(this, childExecutor(group), name, handler); // 實例化含handler的ChannelHandlerContext對象
    }

    private void addFirst0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext nextCtx = head.next;
        newCtx.prev = head;
        newCtx.next = nextCtx;
        head.next = newCtx;     // 新節點插入頭結點后面
        nextCtx.prev = newCtx;
    }

    private void addLast0(AbstractChannelHandlerContext newCtx) {
        AbstractChannelHandlerContext prev = tail.prev;
        newCtx.prev = prev;
        newCtx.next = tail;
        prev.next = newCtx;
        tail.prev = newCtx;     // 新節點插入尾節點前面
    }

ChannelHandlerContext

ChannelHandlerContext是ChannelPipeline雙向鏈表中的節點。 它是連接ChannelHandler和ChannelPipeline的橋梁。有了它ChannelHandler才有機會響應并處理ChannelPipeline中的事件。

其源碼不復雜,其中ChannelHandlerContext的findContextInbound/findContextOutbound 是實現入站事件傳遞給InboundHandler出站事件傳遞給OutboundHandler的關鍵。 其實現也比較簡單,就是判斷context的后續(入站事件)/前驅(出站事件)節點對應的handler實現是否是inbound/outbound,如果不是則遍歷下一個節點,直至尾節點/頭節點。

而在上面的分析中,我們已經知道尾節點實例化時,inbound被設置為ture,頭節點實例化時,outbound被設置為ture。 這便形成的遍歷的終止條件。

    private AbstractChannelHandlerContext findContextInbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.next;
        } while (!ctx.inbound); //直到尾節點,因為尾節點inbound在Pipeline中被定義為Ture
        return ctx;
    }

    private AbstractChannelHandlerContext findContextOutbound() {
        AbstractChannelHandlerContext ctx = this;
        do {
            ctx = ctx.prev;
        } while (!ctx.outbound);//直到頭節點,因為頭節點outbound在Pipeline中被定義為Ture
        return ctx;
    }

正是由于Netty這些優秀的設計,才使得其高性能下,仍然被靈活使用。 因此也被大家所接受并深愛著。


到此,相信大家對“什么是Netty事件傳播”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

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

AI

济宁市| 柳江县| 西宁市| 云林县| 阿拉善盟| 西藏| 龙山县| 绥芬河市| 汉中市| 蕉岭县| 太原市| 仙桃市| 遵化市| 湖口县| 涟源市| 蓝田县| 方山县| 鱼台县| 怀来县| 东明县| 绥江县| 岚皋县| 台南市| 天津市| 加查县| 马龙县| 横峰县| 太仓市| 新绛县| 容城县| 阳西县| 奈曼旗| 万州区| 瓦房店市| 英超| 留坝县| 青岛市| 华坪县| 巴林左旗| 洪雅县| 调兵山市|