欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Netty中的心跳檢測(cè)機(jī)制詳解

 更新時(shí)間:2023年12月11日 11:06:41   作者:warybee  
這篇文章主要介紹了Netty中的心跳檢測(cè)機(jī)制詳解,Netty 是 基于 TCP 協(xié)議開(kāi)發(fā)的,在四層協(xié)議 TCP 協(xié)議的實(shí)現(xiàn)中也提供了 keepalive 報(bào)文用來(lái)探測(cè)對(duì)端是否可用,TCP 層將在定時(shí)時(shí)間到后發(fā)送相應(yīng)的 KeepAlive 探針以確定連接可用性,需要的朋友可以參考下

Netty心跳檢測(cè)機(jī)制

1 心跳檢測(cè)使用場(chǎng)景

長(zhǎng)連接的應(yīng)用場(chǎng)景非常的廣泛,比如監(jiān)控系統(tǒng),IM系統(tǒng),即時(shí)報(bào)價(jià)系統(tǒng),推送服務(wù)等等。像這些場(chǎng)景都是比較注重實(shí)時(shí)性,如果每次發(fā)送數(shù)據(jù)都要進(jìn)行一次DNS解析,建立連接的過(guò)程肯定是極其影響體驗(yàn)。

而長(zhǎng)連接的維護(hù)必然需要一套機(jī)制來(lái)控制。比如 HTTP/1.0 通過(guò)在 header 頭中添加 Connection:Keep-Alive參數(shù),如果當(dāng)前請(qǐng)求需要?;顒t添加該參數(shù)作為標(biāo)識(shí),否則服務(wù)端就不會(huì)保持該連接的狀態(tài),發(fā)送完數(shù)據(jù)之后就關(guān)閉連接。HTTP/1.1以后 Keep-Alive 是默認(rèn)打開(kāi)的。

Netty 是 基于 TCP 協(xié)議開(kāi)發(fā)的,在四層協(xié)議 TCP 協(xié)議的實(shí)現(xiàn)中也提供了 keepalive 報(bào)文用來(lái)探測(cè)對(duì)端是否可用。TCP 層將在定時(shí)時(shí)間到后發(fā)送相應(yīng)的 KeepAlive 探針以確定連接可用性。

Netty 中提供了 tcp-keepalive 的設(shè)置:

在這里插入圖片描述

.childOption(ChannelOption.SO_KEEPALIVE,true) 表示打開(kāi) TCP 的 keepAlive 設(shè)置。

2 Netty心跳檢測(cè)機(jī)制

Netty 中提供了 IdleStateHandler 類專門(mén)用于處理心跳。構(gòu)造函數(shù)如下:

public IdleStateHandler(long readerIdleTime, long writerIdleTime, long allIdleTime,TimeUnit unit) {
    this(false, readerIdleTime, writerIdleTime, allIdleTime, unit);
}

參數(shù)說(shuō)明:

  • readerIdleTime 隔多久檢查一下讀事件是否發(fā)生,如果 channelRead() 方法超過(guò) readerIdleTime 時(shí)間未被調(diào)用則會(huì)觸發(fā)超時(shí)事件調(diào)用 userEventTrigger() 方法
  • writerIdleTime 隔多久檢查一下寫(xiě)事件是否發(fā)生,如果 write() 方法超過(guò) writerIdleTime 時(shí)間未被調(diào)用則會(huì)觸發(fā)超時(shí)事件調(diào)用 userEventTrigger() 方法;
  • allIdleTime 隔多久檢查讀寫(xiě)事件是否發(fā)生
  • unit 時(shí)間單位

可以分別控制讀,寫(xiě),讀寫(xiě)超時(shí)的時(shí)間,如果設(shè)置為0表示不檢測(cè),所以如果全是0,則相當(dāng)于沒(méi)添加這個(gè) IdleStateHandler,連接是個(gè)普通的短連接。

2.1 代碼演示

服務(wù)端

public class TestHeartServer {
    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap bootstrap=new ServerBootstrap();
            bootstrap.group(bossGroup,workerGroup)
                      .channel(NioServerSocketChannel.class)
                      .option(ChannelOption.SO_BACKLOG,128)
                       .childOption(ChannelOption.SO_KEEPALIVE,true)
                       .handler(new LoggingHandler(LogLevel.INFO))//bossGroup處理handler
                       .childHandler(new ChannelInitializer<SocketChannel>() {//workergroup處理handler
                           @Override
                           protected void initChannel(SocketChannel ch) throws Exception {
                               ChannelPipeline pipeline = ch.pipeline();
                               //每隔5s檢查一下是否有讀事件發(fā)生
                               pipeline.addLast(new IdleStateHandler(5,0,0, TimeUnit.SECONDS));
                               pipeline.addLast(new TestHeartServerHandler());
                           }
                       });
            ChannelFuture channelFuture = bootstrap.bind(9999).sync();
            channelFuture.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

服務(wù)端handler

public class TestHeartServerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelActive");
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf=(ByteBuf) msg;
        System.out.println("客戶端消息:"+buf.toString(StandardCharsets.UTF_8));
        //向客戶端發(fā)送消息
        //ctx.writeAndFlush(Unpooled.copiedBuffer("heart",StandardCharsets.UTF_8));
    }
    /**
     *如果5s沒(méi)有讀請(qǐng)求,則向客戶端發(fā)送心跳
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        IdleStateEvent event = (IdleStateEvent) evt;
        switch (event.state()) {
            case READER_IDLE: //讀空閑
                //如果5s沒(méi)有讀請(qǐng)求,則向客戶端發(fā)送心跳
                ctx.writeAndFlush("server send Heartbeat").addListener(ChannelFutureListener.CLOSE_ON_FAILURE);
                break;
            case WRITER_IDLE://寫(xiě)空閑
                break;
            case ALL_IDLE://讀寫(xiě)空閑
                break;
        }
    }
}

客戶端

public class TestHeartClient {
    public static void main(String[] args) {
        EventLoopGroup eventExecutors=new NioEventLoopGroup();
        try {
            Bootstrap bootstrap=new Bootstrap();
            bootstrap.group(eventExecutors)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) throws Exception {
                            ChannelPipeline pipeline = ch.pipeline();
                            //每隔4s檢查一下是否有寫(xiě)事件
                            pipeline.addLast(new IdleStateHandler(0,4,0, TimeUnit.SECONDS));
                            pipeline.addLast(new TestHeartClientHandler());
                        }
                    });
            ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 9999).sync();
            //向服務(wù)端發(fā)送消息
            channelFuture.channel().writeAndFlush(Unpooled.copiedBuffer("Hello server, i'm online", StandardCharsets.UTF_8));
            channelFuture.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            eventExecutors.shutdownGracefully();
        }
    }
}

客戶端Handler

public class TestHeartClientHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        ByteBuf buf=(ByteBuf) msg;
        System.out.println("服務(wù)端發(fā)送的消息:"+buf.toString(StandardCharsets.UTF_8));
    }
    /**
     *
     * @param ctx
     * @param evt
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        IdleStateEvent event = (IdleStateEvent) evt;
        String eventType = null;
        switch (event.state()) {
            //讀空閑
            case READER_IDLE:
                break;
            case WRITER_IDLE://寫(xiě)空閑
                //如果4s沒(méi)有收到寫(xiě)請(qǐng)求,則向服務(wù)端發(fā)送心跳請(qǐng)求
                ctx.writeAndFlush(Unpooled.copiedBuffer("client send Heartbeat",StandardCharsets.UTF_8)).addListener(ChannelFutureListener.CLOSE_ON_FAILURE) ;
                break;
            case ALL_IDLE://讀寫(xiě)空閑
                break;
        }
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
         cause.printStackTrace();
         ctx.close();
    }
}

解釋一下代碼的邏輯:

服務(wù)端添加了:

Copypipeline.addLast(new IdleStateHandler(5, 0, 0, TimeUnit.SECONDS));

每隔5s檢查一下是否有讀事件發(fā)生,如果沒(méi)有就觸發(fā) handler 中的 userEventTriggered(ChannelHandlerContext ctx, Object evt)邏輯。

客戶端添加了:

Copynew IdleStateHandler(0, 4, 0, TimeUnit.SECONDS)

每隔4s檢查一下是否有寫(xiě)事件,如果沒(méi)有就觸發(fā) handler 中的 userEventTriggered(ChannelHandlerContext ctx, Object evt)邏輯。

到此這篇關(guān)于Netty中的心跳檢測(cè)機(jī)制詳解的文章就介紹到這了,更多相關(guān)Netty心跳檢測(cè)機(jī)制內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • SpringBoot整合MD5加密完成注冊(cè)和登錄方式

    SpringBoot整合MD5加密完成注冊(cè)和登錄方式

    MD5(MessageDigestAlgorithm5)是一種常見(jiàn)的哈希算法,用于生成固定長(zhǎng)度(128位)的哈希值,主要應(yīng)用于數(shù)據(jù)完整性校驗(yàn)和密碼存儲(chǔ),MD5具有快速計(jì)算、不可逆性和抗碰撞性等特點(diǎn),盡管存在碰撞漏洞,MD5仍廣泛應(yīng)用于文件下載校驗(yàn)和數(shù)字簽名等場(chǎng)景
    2024-10-10
  • Java多種方式實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式

    Java多種方式實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式

    這篇文章主要介紹了Java多種方式實(shí)現(xiàn)生產(chǎn)者消費(fèi)者模式,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-07-07
  • 基于java web獲取網(wǎng)頁(yè)訪問(wèn)次數(shù)代碼實(shí)例

    基于java web獲取網(wǎng)頁(yè)訪問(wèn)次數(shù)代碼實(shí)例

    這篇文章主要介紹了基于java web獲取網(wǎng)頁(yè)訪問(wèn)次數(shù)代碼實(shí)例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-02-02
  • Java編譯錯(cuò)誤問(wèn)題:需要class,interface或enum

    Java編譯錯(cuò)誤問(wèn)題:需要class,interface或enum

    這篇文章主要介紹了Java編譯錯(cuò)誤問(wèn)題:需要class,interface或enum,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-02-02
  • 通過(guò)prometheus監(jiān)控springboot程序運(yùn)行狀態(tài)的操作流程

    通過(guò)prometheus監(jiān)控springboot程序運(yùn)行狀態(tài)的操作流程

    jmx_exporter用于從Java應(yīng)用程序中提取JMX指標(biāo),適用于SpringBoot應(yīng)用,通過(guò)下載jar包和配置文件,可以抓取JVM基礎(chǔ)指標(biāo),要獲取應(yīng)用級(jí)別指標(biāo),需要集成Prometheus客戶端庫(kù)并自定義指標(biāo),本文給大家介紹了如何通過(guò)prometheus監(jiān)控springboot程序運(yùn)行狀態(tài)
    2025-02-02
  • java性能優(yōu)化之代碼緩存優(yōu)化

    java性能優(yōu)化之代碼緩存優(yōu)化

    這篇文章主要介紹了java性能優(yōu)化之代碼緩存優(yōu)化,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容介紹,具有一定的參考價(jià)值,需要的小伙伴可以參考一下
    2022-07-07
  • JavaApi實(shí)現(xiàn)更新刪除及讀取節(jié)點(diǎn)

    JavaApi實(shí)現(xiàn)更新刪除及讀取節(jié)點(diǎn)

    這篇文章主要介紹了JavaApi實(shí)現(xiàn)更新刪除及讀取節(jié)點(diǎn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2020-05-05
  • Java中switch-case結(jié)構(gòu)的使用方法舉例詳解

    Java中switch-case結(jié)構(gòu)的使用方法舉例詳解

    這篇文章主要介紹了Java中switch-case結(jié)構(gòu)使用的相關(guān)資料,switch-case結(jié)構(gòu)是Java中處理多個(gè)分支條件的一種有效方式,它根據(jù)一個(gè)表達(dá)式的值來(lái)執(zhí)行不同的代碼塊,需要的朋友可以參考下
    2025-01-01
  • SpringBoot整合Apollo配置中心快速使用詳解

    SpringBoot整合Apollo配置中心快速使用詳解

    本文主要介紹了SpringBoot整合Apollo配置中心快速使用詳解,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2021-09-09
  • Java中JSON字符串與java對(duì)象的互換實(shí)例詳解

    Java中JSON字符串與java對(duì)象的互換實(shí)例詳解

    這篇文章主要介紹了在java中,JSON字符串與java對(duì)象的相互轉(zhuǎn)換實(shí)例詳解,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下
    2016-08-08

最新評(píng)論