Netty+SpringBoot+FastDFS+Html5實現聊天App(六)

Netty+SpringBoot+FastDFS+Html5實現聊天App,項目介紹

Netty+SpringBoot+FastDFS+Html5實現聊天App,項目github鏈接

本章完整代碼鏈接

本章將給聊天App_PigChat加上心跳機制。



爲什麼要實現心跳機制

如果沒有特意的設置某些選項或者實現應用層心跳包,TCP空閒的時候是不會發送任何數據包。也就是說,當一個TCP的socket,客戶端與服務端誰也不發送數據,會一直保持着連接。這其中如果有一方異常掉線(例如死機、路由被破壞、防火牆切斷連接等),另一端如果沒有發送數據,永遠也不可能知道。這對於一些服務型的程序來說,是災難性的後果,將會導致服務端socket資源耗盡

舉個簡單的例子,當我們因爲特殊情況打開飛行模式 ,在處理完事件之後再關閉飛行模式,這時候如果再進入應用程序中,我們將以新的channel進入,但是之前的channel還是會保留。

因此,爲了保證連接的有效性、及時有效地檢測到一方的非正常斷開,保證連接的資源被有效的利用,我們就會需要一種保活的機制,通常改機制兩種處理方式:

1、利用TCP協議層實現的Keepalive;

2、自己在應用層實現心跳包。



實現心跳機制

新建一個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    ======================
        
        
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章