Netty心跳檢測
Netty給我們提供三個(gè)Handler,分別是IdleStateHandler、ReadTimeoutHandler、WriteTimeOutHandler,主要目的是檢查對方是否還在線
為什么需要心跳機(jī)制
TCP協(xié)議適用于客戶端數(shù)量相對較少,并且頻繁通信的業(yè)務(wù)場景;HTTP協(xié)議使用與客戶端數(shù)量比較大的業(yè)務(wù)場景;HTTP是短鏈接,請求完成后會(huì)釋放連接資源,不占用服務(wù)器資源,但是TCP連接成功則可以多次請求,不會(huì)釋放,除非特殊原因?qū)е逻B接失敗
長鏈接不會(huì)釋放鏈接資源,那么很多客戶端只是完成了連接,但是沒有實(shí)際的業(yè)務(wù)請求操作,那么服務(wù)器的資源還是被占用,導(dǎo)致服務(wù)器性能下降。
三個(gè)核心類
| IdleStateHandler | 當(dāng)連接空閑時(shí)間(讀或?qū)懀┨L時(shí),將觸發(fā) IdleStateEvent 事件,可以通過 ChannelInboundHandler 中重寫 userEventTrigged 方法來處理該事件。 |
|---|---|
| ReadTimeoutHandler | 如果在指定的時(shí)間之內(nèi)沒有發(fā)生讀事件,就會(huì)拋出這個(gè)異常,并且自動(dòng)關(guān)閉連接??梢栽?exectionCaught 方法中處理這個(gè)異常。 |
| WriteTimeoutHandler | 如果在指定的時(shí)間之內(nèi)沒有發(fā)生寫事件,拋出次異常,并且關(guān)閉連接??梢栽?exectionCaught 方法中處理這個(gè)異常。 |
服務(wù)端
pipeline.addLast(new LoggingHandler(LogLevel.DEBUG));
//5秒鐘之內(nèi)沒有 讀事件 則斷開連接
pipeline.addLast(new ReadTimeoutHandler(5,TimeUnit.SECONDS));
//字符串解碼器
pipeline.addLast(new StringDecoder(Charset.forName("GBK")));
//字符串編碼器
pipeline.addLast(new StringEncoder(Charset.forName("GBK")));
//業(yè)務(wù)Handler
pipeline.addLast(new HeartBeatHandler());
public class HeartBeatHandler 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());
}
}
客戶端
ch.pipeline().addLast(new StringDecoder(Charset.forName("GBK")));
// 解碼轉(zhuǎn)String,注意調(diào)整自己的編碼格式GBK、UTF-8
ch.pipeline().addLast(new StringEncoder(Charset.forName("GBK")));
//實(shí)例:延遲 1 秒鐘,每個(gè) 15 秒鐘往服務(wù)端發(fā)送一次 hello world。
//心跳檢測http://www.imooc.com/wiki/nettylesson/netty25.html
f.channel().eventLoop().scheduleWithFixedDelay(() -> {
f.channel().writeAndFlush("hello world!");
}, 1, 15, TimeUnit.SECONDS);
代碼說明
客戶端每個(gè)15秒發(fā)送一次數(shù)據(jù),
服務(wù)端如果5秒之內(nèi)沒有讀事件,則自動(dòng)端口連接
因?yàn)槊看味际歉?5秒發(fā)送,客戶端每次發(fā)送的數(shù)據(jù)都是超時(shí)了,因此,連接會(huì)被斷開
更改代碼
f.channel().writeAndFlush("hello world!");
}, 1, 1, TimeUnit.SECONDS);
服務(wù)端執(zhí)行結(jié)果

FRVVh.png
