Netty+SpringBoot+FastDFS+Html5實現聊天App,項目介紹。
java
Netty+SpringBoot+FastDFS+Html5實現聊天App,項目github連接。
git
本章完整代碼連接。
github
本章將給聊天App_PigChat加上心跳機制。segmentfault
若是沒有特地的設置某些選項或者實現應用層心跳包,TCP空閒的時候是不會發送任何數據包。也就是說,當一個TCP的socket,客戶端與服務端誰也不發送數據,會一直保持着鏈接。這其中若是有一方異常掉線(例如死機、路由被破壞、防火牆切斷鏈接等),另外一端若是沒有發送數據,永遠也不可能知道。這對於一些服務型的程序來講,是災難性的後果,將會致使服務端socket資源耗盡。socket
舉個簡單的例子,當咱們由於特殊狀況打開飛行模式 ,在處理完事件以後再關閉飛行模式,這時候若是再進入應用程序中,咱們將以新的channel進入,可是以前的channel仍是會保留。ide
所以,爲了保證鏈接的有效性、及時有效地檢測到一方的非正常斷開,保證鏈接的資源被有效的利用,咱們就會須要一種保活的機制,一般改機制兩種處理方式:netty
一、利用TCP協議層實現的Keepalive;code
二、本身在應用層實現心跳包。繼承
新建一個HeartBeatHandler用於檢測channel的心跳。事件
繼承ChannelInboundHandlerAdapter,並重寫其userEventTriggered方法。當客戶端的全部ChannelHandler中4s內沒有write事件,則會觸發userEventTriggered方法。
首先咱們判斷evt是不是IdleStateEvent的實例,IdleStateEvent用於觸發用戶事件,包含讀空閒/寫空閒/讀寫空閒。
對evt進行強制履行轉換後,經過state判斷其狀態,只有當其該channel處於讀寫空閒的時候纔將這個channel關閉。
/** * @Description: 用於檢測channel的心跳handler * 繼承ChannelInboundHandlerAdapter,從而不須要實現channelRead0方法 */ public class HeartBeatHandler extends ChannelInboundHandlerAdapter { @Override public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception { // 判斷evt是不是IdleStateEvent(用於觸發用戶事件,包含 讀空閒/寫空閒/讀寫空閒 ) if (evt instanceof IdleStateEvent) { IdleStateEvent event = (IdleStateEvent)evt; // 強制類型轉換 if (event.state() == IdleState.READER_IDLE) { System.out.println("進入讀空閒..."); } else if (event.state() == IdleState.WRITER_IDLE) { System.out.println("進入寫空閒..."); } else if (event.state() == IdleState.ALL_IDLE) { System.out.println("channel關閉前,users的數量爲:" + ChatHandler.users.size()); Channel channel = ctx.channel(); // 關閉無用的channel,以防資源浪費 channel.close(); System.out.println("channel關閉後,users的數量爲:" + ChatHandler.users.size()); } } } }
在原來的WSServerInitialzer中增長心跳機制的支持。
// ====================== 增長心跳支持 start ====================== // 針對客戶端,若是在1分鐘時沒有向服務端發送讀寫心跳(ALL),則主動斷開 // 若是是讀空閒或者寫空閒,不處理 pipeline.addLast(new IdleStateHandler(8, 10, 12)); // 自定義的空閒狀態檢測 pipeline.addLast(new HeartBeatHandler()); // ====================== 增長心跳支持 end ======================