第七色在线视频,2021少妇久久久久久久久久,亚洲欧洲精品成人久久av18,亚洲国产精品特色大片观看完整版,孙宇晨将参加特朗普的晚宴

Netty 心跳檢測(cè)

1. 前言

本節(jié),我們主要講解心跳機(jī)制 heartbeat,Netty 給我們提供了三個(gè) Handler,分別是 IdleStateHandlerReadTimeoutHandler、WriteTimeoutHandler,主要目的是檢查對(duì)方是否有效,也就是說(shuō)對(duì)方是否還在線。

2. 為什么需要心跳機(jī)制

了解 TCP: TCP 協(xié)議適用于客戶(hù)端數(shù)量相對(duì)比較少,并且通信頻繁的業(yè)務(wù)場(chǎng)景;Http 協(xié)議則適用于客戶(hù)端數(shù)量比較大的業(yè)務(wù)場(chǎng)景。因?yàn)?Http 是短連接,請(qǐng)求完成即會(huì)釋放連接資源,不再占用服務(wù)器資源,但是,TCP 則不會(huì),連接成功,則可以多次請(qǐng)求,不會(huì)釋放,除非特殊原因?qū)е逻B接斷開(kāi)。

面臨問(wèn)題: 既然長(zhǎng)連接是不會(huì)釋放連接資源,那么如果很多客戶(hù)端只是完成了連接,但是并沒(méi)有實(shí)際的業(yè)務(wù)請(qǐng)求操作,那么服務(wù)器的資源還是被占用,導(dǎo)致服務(wù)器性能下降。

解決辦法: 把那些長(zhǎng)期占用連接資源,但是并沒(méi)有實(shí)際業(yè)務(wù)操作的連接斷開(kāi)掉,等它們需要做業(yè)務(wù)操作的時(shí)候,再重連服務(wù)器。這樣可以達(dá)到即使釋放沒(méi)用的資源,提高服務(wù)器的性能。

總結(jié),心跳機(jī)制主要有以下兩個(gè)方面的作用

  1. 定時(shí)剔除哪些沒(méi)用的連接,減輕服務(wù)端的壓力;
  2. 適用于中間件(比如:RPC 框架),服務(wù)端規(guī)定時(shí)間內(nèi)沒(méi)用收到客戶(hù)端的心跳數(shù)據(jù),則可以認(rèn)為其宕機(jī),服務(wù)端剔除對(duì)于的映射關(guān)系。

圖片描述

3. 三個(gè)核心類(lèi)講解

為了實(shí)現(xiàn)以上需求,Netty 給我們提供了幾個(gè)特殊的 Handler 類(lèi)。

名稱(chēng) 作用
IdleStateHandler 當(dāng)連接空閑時(shí)間(讀或?qū)懀┨L(zhǎng)時(shí),將觸發(fā) IdleStateEvent 事件,可以通過(guò) ChannelInboundHandler 中重寫(xiě) userEventTrigged 方法來(lái)處理該事件。
ReadTimeoutHandler 如果在指定的時(shí)間之內(nèi)沒(méi)有發(fā)生讀事件,就會(huì)拋出這個(gè)異常,并且自動(dòng)關(guān)閉連接??梢栽?exectionCaught 方法中處理這個(gè)異常。
WriteTimeoutHandler 如果在指定的時(shí)間之內(nèi)沒(méi)有發(fā)生寫(xiě)事件,拋出次異常,并且關(guān)閉連接??梢栽?exectionCaught 方法中處理這個(gè)異常。

IdleStateHandler 構(gòu)造函數(shù)說(shuō)明

/*
* readerIdleTimeSeconds 讀事件空閑時(shí)間,如果為0則表示禁用
* writerIdleTimeSeconds 寫(xiě)事件空閑時(shí)間,如果為0則表示禁用
* allIdleTimeSeconds 讀寫(xiě)事件空閑時(shí)間
*/
public IdleStateHandler(int readerIdleTimeSeconds, int writerIdleTimeSeconds, int allIdleTimeSeconds) {
    
}

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

總結(jié):都是利用定時(shí)器調(diào)度任務(wù)完成。 IdleStateHandler 超時(shí)調(diào)用 handler 的 userEventTriggered 方法。ReadTimeOutHandler 超時(shí)拋出異常,調(diào)用 handler 的 exceptionCaught 方法,并且會(huì)關(guān)閉 channel。

4. 案例測(cè)試

4.1 服務(wù)端

實(shí)例:

ChannelPipeline pipeline = ch.pipeline();

//5秒鐘沒(méi)有讀事件,則斷開(kāi)連接
pipeline.addLast(new ReadTimeoutHandler(5, TimeUnit.SECONDS));
//5秒鐘沒(méi)有寫(xiě)事件,則斷開(kāi)連接
pipeline.addLast(new WriteTimeoutHandler(5, TimeUnit.SECONDS));
//解碼器
pipeline.addLast(new StringDecoder());
//編碼器
pipeline.addLast(new StringEncoder());
//業(yè)務(wù)Handler
pipeline.addLast(new HeartBeanHandler());
public class HeartBeanHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        System.out.println("channelRead>>>"+msg+">>>"+ LocalDateTime.now());
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        System.out.println("exceptionCaught>>>"+cause.getMessage());
    }
}

4.2 客戶(hù)端 1

實(shí)例:延遲 1 秒鐘,每個(gè) 15 秒鐘往服務(wù)端發(fā)送一次 hello world。

channelFuture.channel().eventLoop().scheduleWithFixedDelay(new Runnable() {
    public void run() {
        channelFuture.channel().writeAndFlush("hello world");
    }    
},1,15, TimeUnit.SECONDS);

服務(wù)端執(zhí)行結(jié)果:

channelRead>>>hello world>>>2020-07-26T15:16:08.893
exceptionCaught>>>null

客戶(hù)端執(zhí)行結(jié)果:

客戶(hù)端關(guān)閉了
Process finished with exit code 0

代碼說(shuō)明:

  1. 客戶(hù)端每隔 15 秒發(fā)送一次數(shù)據(jù);
  2. 服務(wù)端如果 5 秒之內(nèi)沒(méi)有讀寫(xiě)事件,則自動(dòng)斷開(kāi)連接;
  3. 從時(shí)間設(shè)置上來(lái)看,客戶(hù)端每次發(fā)送數(shù)據(jù)都是超時(shí)了,因此,連接會(huì)被斷開(kāi)。

4.3 客戶(hù)端 2

實(shí)例:延遲 1 秒鐘,每個(gè) 3 秒鐘往服務(wù)端發(fā)送一次 hello world。

channelFuture.channel().eventLoop().scheduleWithFixedDelay(new Runnable() {
    public void run() {
        channelFuture.channel().writeAndFlush("hello world");
    }    
},1,3, TimeUnit.SECONDS);

服務(wù)端執(zhí)行結(jié)果:

channelRead>>>hello world>>>2020-07-26T15:15:10.889
channelRead>>>hello world>>>2020-07-26T15:15:13.892
channelRead>>>hello world>>>2020-07-26T15:15:16.893
channelRead>>>hello world>>>2020-07-26T15:15:19.894

代碼說(shuō)明:

  1. 客戶(hù)端每隔 3 秒發(fā)送一次數(shù)據(jù);
  2. 服務(wù)端如果 5 秒之內(nèi)沒(méi)有讀寫(xiě)事件,則自動(dòng)斷開(kāi);
  3. 從時(shí)間設(shè)置上來(lái)看,客戶(hù)端每次發(fā)送數(shù)據(jù)的時(shí)間都在超時(shí)時(shí)間范圍之內(nèi),因此,連接不會(huì)被斷開(kāi)。

4.4 特殊說(shuō)明

ReadTimeoutHandler 和 WriteTimeoutHandler 既可以用于客戶(hù)端,也可以用于服務(wù)端,或者兩邊同時(shí)使用。常見(jiàn)的業(yè)務(wù)場(chǎng)景如下所示:

場(chǎng)景一: 如果是服務(wù)端往客戶(hù)端推送消息(消息推送),則 WriteTimeoutHandler 用于服務(wù)端,ReadTimeoutHandler 用于客戶(hù)端;
場(chǎng)景二: 如果是客戶(hù)端主動(dòng)發(fā)起請(qǐng)求的業(yè)務(wù)(比如:IM),則 WriteTimeoutHandler 用于客戶(hù)端,ReadTimeoutHandler 用于服務(wù)端。

4.5 IdleStateHandler 的使用

實(shí)例:管道中添加 IdleStateHandler

// 空閑檢測(cè)
ch.pipeline().addLast(new IdleStateHandler(60,45,20,TimeUnit.SECONDS));
// 業(yè)務(wù)Handler
ch.pipeline().addLast(new HeartBeatHandler());

5. 小結(jié)

本節(jié)主要掌握的知識(shí)點(diǎn)

  1. 為什么需要做心跳檢測(cè),以及它的常見(jiàn)作用,分別是:主動(dòng)剔除無(wú)用連接減輕服務(wù)端壓力、用于中間件的心跳檢測(cè);
  2. Netty 提了三個(gè)核心類(lèi),分別是 IdleStateHandlerReadTimeoutHandler、WriteTimeoutHandler,它們的作用以及使用方法。