成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

聊聊 Netty 客戶端斷線重連的設計與實現

網絡
本文我們基于 Netty 生命周期的源碼剖析給出客戶端斷線重連的設計和落地思路,希望對你有幫助。

其實Netty基于網絡連接聲明周期暴露了很多提供用戶自實現的API,而本文將基于其中的一個拓展點實現連接可靠性,希望對你有幫助。

詳解Netty客戶端斷線重連的設計和實現

Netty生命周期中的channelInactive方法

讀過筆者往期文章的讀者大體是都知道channelInactive這個回調方法,我們從其注釋即可知曉:注冊的ChannelHandlerContext 的 Channel現在已經是不活躍即已經不可用的連接,就會調用pipeline上所有的處理器執行其內部實現的channelInactive處理剩余業務:

 /**
     * The {@link Channel} of the {@link ChannelHandlerContext} was registered is now inactive and reached its
     * end of lifetime.
     */
    void channelInactive(ChannelHandlerContext ctx) throws Exception;

實際上channelInactive的執行我們也可以通過源碼的方式讓讀者了解,我們以客戶端連接為例,一旦客戶端斷開連接,客戶端的selector就會輪循到連接關閉事件,便會將對應客戶端的channel取消并調用channelInactive方法:

從源碼角度來NioEventLoop輪詢到關閉事件后會直接執行該事件closeOnRead方法,其內部判斷連接非open狀態則會直接調用close進行連接關閉操作:

protected class NioByteUnsafe extends AbstractNioUnsafe {

        private void closeOnRead(ChannelPipeline pipeline) {
            if (isOpen()) {
                //......
                } else {
                 //調用close執行關閉連接
                    close(voidPromise());
                }
            }
        }

close邏輯內部最終會定位到客戶端的socketchannel執行到AbstractChannel的close方法,其內部會向eventLoop注冊一個doDeregister的事件,該事件會將客戶端socket注冊的讀寫事件取消,完成后就會調用fireChannelInactive走到channelInactive回調,通知當前客戶端netty這個socket的遠程連接不再活躍,已經斷開了:

對此我們給出上圖所示的源碼片段,改代碼位于AbstractChannel的close方法,其內部核心邏輯就是調用fireChannelInactiveAndDeregister移除客戶端socket的讀寫事件并觸發channelInactive的回調通知:

private void close(final ChannelPromise promise, final Throwable cause,
                           final ClosedChannelException closeCause, final boolean notify) {
           //......

          
            if (closeExecutor != null) {
                 //......
            } else {
                 //......
                } else {
                //調用fireChannelInactiveAndDeregister移除斷開連接的客戶端socket并觸發channelInactive回調
                    fireChannelInactiveAndDeregister(wasActive);
                }
            }
        }

fireChannelInactiveAndDeregister內部核心邏輯就是deregister方法,可以看到該方法核心邏輯就是提交給eventLoop一個異步任務,也就是我們上圖所說的移除客戶端讀寫事件的方法,方法名是doDeregister,完成該方法調用后就會調用fireChannelInactive方法,告知服務端這個客戶端channel連接已斷開:

private void deregister(final ChannelPromise promise, final boolean fireChannelInactive) {
           //......
            invokeLater(new Runnable() {
                @Override
                public void run() {
                    try {
                    //移除客戶端讀寫事件
                        doDeregister();
                    } catch (Throwable t) {
                        logger.warn("Unexpected exception occurred while deregistering a channel.", t);
                    } finally {
                    //觸發客戶端channel的channelInactive回調
                        if (fireChannelInactive) {
                            pipeline.fireChannelInactive();
                        }
                      //......
                    }
                }
            });
        }

對此我們給出doDeregister的邏輯,可以看到其內部拿到eventLoop事件輪詢器,通過調用cancel移除當前客戶端socket讀寫事件:

   @Override
    protected void doDeregister() throws Exception {
    //通過selectionKey獲取斷開連接的客戶端讀寫事件的key,通過cancel移除這些事件
        eventLoop().cancel(selectionKey());
    }

Netty斷線重連思路與實現

由此我們知曉要想實現斷線重連,客戶端可以通過重寫channelInactive方法,確保在感知到連接斷開時再次提交一個連接的延遲事件,知道斷線的連接再次恢復,由此保證客戶端連接可靠性:

最終我們給出斷線重連的ReconnectHandler,其內部邏輯很簡單,延遲5秒后向eventLoop提交一個斷線重連的異步連接任務直到成功,完成后我們將這個處理器添加到客戶端的pipeline即可:

public class ReconnectHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {

  //提交斷線重連的延遲任務
        scheduledDoReConnect(ctx);
        
        ctx.fireChannelInactive();
    }


    private ScheduledFuture<?> scheduledDoReConnect(ChannelHandlerContext ctx) {
        //拿到當前channel的eventLoop提交一個連接遠程服務端的延遲任務
        ScheduledFuture<?> scheduledFuture = ctx.channel().eventLoop().schedule(() -> {
            ChannelFuture channelFuture = ctx.channel().connect(new InetSocketAddress("127.0.0.1", 8888));
            channelFuture.addListener(f -> {
                if (!f.isSuccess()) {
                    //如果失敗則遞歸調用scheduledDoReConnect再次嘗試
                    scheduledDoReConnect(ctx);
                } else {
                    System.out.println("reconnect success.");
                }
            });

        }, 5, TimeUnit.SECONDS);


        return scheduledFuture;

    }

}

小結

自此我們基于Netty生命周期的源碼剖析給出客戶端斷線重連的設計和落地思路,希望對你有幫助。

責任編輯:趙寧寧 來源: 寫代碼的SharkChili
相關推薦

2024-09-06 11:11:20

2024-12-23 06:00:00

TCPC#網絡

2010-05-31 10:11:32

瘦客戶端

2009-08-21 15:36:41

服務端與客戶端

2009-08-21 15:54:40

服務端與客戶端

2021-09-22 15:46:29

虛擬桌面瘦客戶端胖客戶端

2022-08-16 08:17:09

CDPCRM數據

2023-05-26 08:24:17

短信渠道模型

2011-03-07 13:50:20

2021-10-14 08:39:17

Java Netty Java 基礎

2021-11-07 19:06:57

爬蟲網斷JS

2010-12-17 10:16:33

OpenVAS

2010-08-31 16:29:40

DHCP客戶端

2009-02-04 17:39:14

ibmdwWebSphereDataPower

2011-03-21 14:53:36

Nagios監控Linux

2011-04-06 14:24:20

Nagios監控Linux

2011-08-17 10:10:59

2025-03-20 09:54:47

2025-02-25 09:29:34

2022-10-18 08:28:38

運營活動實現邏輯整體協作
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 精品久久久久一区二区国产 | 91在线资源 | 这里只有精品99re | 国产精品久久久久久久久久久久 | 一区二区三区视频免费看 | 久久精选 | 亚洲一二三区在线观看 | 久久久久久国产 | 玩丰满女领导对白露脸hd | 亚洲成人午夜电影 | 国产黄视频在线播放 | 亚洲最色网站 | 欧美一区二区视频 | 久久伊| 欧美精品在线免费观看 | 91精品国产91久久综合桃花 | 欧美欧美欧美 | 9久久精品 | 成人免费黄色片 | 中文成人在线 | 免费成人高清在线视频 | 久久久久国产一区二区三区 | 麻豆国产一区二区三区四区 | 麻豆av在线免费观看 | 成人免费观看男女羞羞视频 | 精品欧美色视频网站在线观看 | 中文字幕日韩在线观看 | 欧美a√| 精品欧美一区二区中文字幕视频 | 亚洲第一色站 | 91九色视频在线 | 日日操网站 | 激情一区 | 国产视频福利 | 羞羞视频免费观 | 国产精品海角社区在线观看 | 久久久久国产视频 | 国际精品鲁一鲁一区二区小说 | 国产xxxx搡xxxxx搡麻豆 | 免费看一区二区三区 | 草久久久|