netty(十八)Netty提升 - 連接假死如何處理甥温?

一、連接假死出現(xiàn)原因

在網(wǎng)絡(luò)編程的領(lǐng)域當(dāng)中妓布,很多問題都會莫名其妙的出現(xiàn)姻蚓,讓人措手不及。

其中一種匣沼,就是連接假死狰挡,那么連接假死是如何出現(xiàn)的呢?可能存在以下幾種情況:

1)網(wǎng)絡(luò)設(shè)備出現(xiàn)故障释涛。例如網(wǎng)卡加叁,機(jī)房等,底層的 TCP 連接已經(jīng)斷開了唇撬,但應(yīng)用程序沒有感知到它匕,仍然占用著資源。

2)公網(wǎng)網(wǎng)絡(luò)不穩(wěn)定窖认,出現(xiàn)丟包豫柬。如果連續(xù)出現(xiàn)丟包,這時(shí)現(xiàn)象就是客戶端數(shù)據(jù)發(fā)不出去扑浸,服務(wù)端也一直收不到數(shù)據(jù)烧给,進(jìn)程一直占據(jù)資源,耗在這兒首装。

3)應(yīng)用程序線程阻塞,無法進(jìn)行數(shù)據(jù)讀寫杭跪。

連接假死會產(chǎn)生以下問題:

1)假死的連接占用的資源不能自動釋放仙逻。

2)向假死的連接發(fā)送數(shù)據(jù),得到的反饋是發(fā)送超時(shí)涧尿。

二系奉、如何解決連接假死?

Netty提供了一個(gè)叫做IdleStateHandler的處理器,用來進(jìn)行空閑檢測姑廉。

其實(shí)現(xiàn)方式是:

當(dāng)Channel有一段時(shí)間沒有執(zhí)行讀缺亮、寫或兩者操作時(shí)觸發(fā)IdleStateEvent。

有三個(gè)主要參數(shù):

  • readerIdleTime:一個(gè)IdleStateEvent桥言,其狀態(tài)是IdleState.READER_IDLE時(shí)的指定時(shí)間段內(nèi)萌踱,沒有執(zhí)行讀操作將被觸發(fā)葵礼。 指定0以禁用。
  • writerIdleTime:一個(gè)IdleStateEvent并鸵,其狀態(tài)是IdleState.WRITER_IDLE時(shí)的指定時(shí)間段內(nèi)鸳粉,沒有執(zhí)行寫操作將被觸發(fā)。 指定0以禁用园担。
  • allIdleTime:一個(gè)IdleStateEvent届谈,其狀態(tài)是IdleState.ALL_IDLE時(shí)的指定時(shí)間段內(nèi),沒有進(jìn)行讀取和寫入都將被觸發(fā)弯汰。 指定0以禁用

我們正常使用時(shí)艰山,也使用這個(gè)三個(gè)參數(shù)的構(gòu)造即可:

    public IdleStateHandler(
            int readerIdleTimeSeconds,
            int writerIdleTimeSeconds,
            int allIdleTimeSeconds) {

        this(readerIdleTimeSeconds, writerIdleTimeSeconds, allIdleTimeSeconds,
             TimeUnit.SECONDS);
    }

如上所示,其默認(rèn)單位是秒咏闪,當(dāng)然也有可以指定單位的構(gòu)造曙搬,還能附帶考慮buf處理數(shù)據(jù)時(shí)間的構(gòu)造,這里就不多介紹了汤踏。

接下來我們看看如何使用织鲸,我們需要將這個(gè)處理器添加到pipeline當(dāng)中,需要注意的是溪胶,我們需要自己去處理事件搂擦,IdleStateEvent。

關(guān)于這個(gè)事件的處理哗脖,我們不能使用常規(guī)的入站或者出站處理器了瀑踢,此處需要學(xué)習(xí)一個(gè)新的處理器,專門用來處理特殊事件的才避,我通過下面的代碼進(jìn)行演示:

服務(wù)端接收數(shù)據(jù)橱夭,添加如下代碼:

                    //空閑檢測處理器,檢測5秒內(nèi)未讀取
                    ch.pipeline().addLast(new IdleStateHandler(5, 0, 0));
                    //可以同時(shí)作為入站和出站處理器桑逝,此處用來處理特殊事件
                    ch.pipeline().addLast(new ChannelDuplexHandler() {
                        //用戶事件觸發(fā)
                        @Override
                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                            IdleStateEvent stateEvent = (IdleStateEvent) evt;
                            //我們的服務(wù)器端只進(jìn)行數(shù)據(jù)接收
                            if (stateEvent.state() ==  IdleState.READER_IDLE) {
                                System.out.println("已經(jīng)5秒沒有接收到數(shù)據(jù)");
                            }
                        }
                    });

客戶端發(fā)送數(shù)據(jù)棘劣,添加如下代碼:

                   //空閑檢測處理器,檢測5秒未寫入
                    ch.pipeline().addLast(new IdleStateHandler(0, 5, 0));
                    //可以同時(shí)作為入站和出站處理器楞遏,此處用來處理特殊事件
                    ch.pipeline().addLast(new ChannelDuplexHandler() {
                        //用戶事件觸發(fā)
                        @Override
                        public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
                            IdleStateEvent stateEvent = (IdleStateEvent) evt;
                            //我們的服務(wù)器端只進(jìn)行數(shù)據(jù)接收
                            if (stateEvent.state() ==  IdleState.WRITER_IDLE) {
                                System.out.println("已經(jīng)5秒沒有寫入數(shù)據(jù)");
                            }
                        }
                    });

當(dāng)客戶端和服務(wù)端都啟動并建立連接后茬暇,如果沒有消息就會打印如下內(nèi)容:

已經(jīng)5秒沒有寫入數(shù)據(jù)
已經(jīng)5秒沒有寫入數(shù)據(jù)
已經(jīng)5秒沒有寫入數(shù)據(jù)
已經(jīng)5秒沒有寫入數(shù)據(jù)
... ...
已經(jīng)5秒沒有讀取到數(shù)據(jù)
已經(jīng)5秒沒有讀取到數(shù)據(jù)
已經(jīng)5秒沒有讀取到數(shù)據(jù)
已經(jīng)5秒沒有讀取到數(shù)據(jù)
... ...

其實(shí)還有后續(xù)的操作,就是寡喝,當(dāng)我們檢測到在一定時(shí)間內(nèi)沒有發(fā)生數(shù)據(jù)寫入或讀取糙俗,應(yīng)該怎么做?

可以制定一些策略预鬓,如連續(xù)多少次檢測到空閑等巧骚。最終我們要做的其實(shí)就是釋放資源:

ctx.channel().close();

上述的代碼實(shí)際并不友好,其實(shí)比較好的處理方式,需要結(jié)合業(yè)務(wù)區(qū)考慮劈彪,沒有消息讀取并不代表連接存在問題竣蹦,可以使用下面的方式,心跳檢測

客戶端:當(dāng)檢測到?jīng)]有數(shù)據(jù)寫入時(shí)粉臊,可以定時(shí)向服務(wù)端發(fā)送心跳草添,比如每5秒就向服務(wù)端寫入一次數(shù)據(jù)。這個(gè)時(shí)間要小于服務(wù)器設(shè)置的檢測時(shí)間扼仲。

服務(wù)端:設(shè)置一個(gè)定時(shí)讀取的檢測時(shí)間远寸,比如8秒,這樣在8秒內(nèi)屠凶,一定會受到客戶端的心跳驰后,如果超過8秒沒有心跳,則可以認(rèn)為連接出現(xiàn)問題矗愧,可以關(guān)閉channel灶芝。


關(guān)于空閑檢測的內(nèi)容,就介紹這么多唉韭,有用的話點(diǎn)個(gè)贊再走吧R固椤!

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末属愤,一起剝皮案震驚了整個(gè)濱河市女器,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌住诸,老刑警劉巖驾胆,帶你破解...
    沈念sama閱讀 216,651評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異贱呐,居然都是意外死亡丧诺,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,468評論 3 392
  • 文/潘曉璐 我一進(jìn)店門奄薇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來驳阎,“玉大人,你說我怎么就攤上這事馁蒂『峭恚” “怎么了?”我有些...
    開封第一講書人閱讀 162,931評論 0 353
  • 文/不壞的土叔 我叫張陵远搪,是天一觀的道長劣纲。 經(jīng)常有香客問我逢捺,道長谁鳍,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,218評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮倘潜,結(jié)果婚禮上绷柒,老公的妹妹穿的比我還像新娘。我一直安慰自己涮因,他們只是感情好废睦,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,234評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著养泡,像睡著了一般嗜湃。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上澜掩,一...
    開封第一講書人閱讀 51,198評論 1 299
  • 那天购披,我揣著相機(jī)與錄音,去河邊找鬼肩榕。 笑死刚陡,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的株汉。 我是一名探鬼主播筐乳,決...
    沈念sama閱讀 40,084評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼乔妈!你這毒婦竟也來了蝙云?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,926評論 0 274
  • 序言:老撾萬榮一對情侶失蹤褒翰,失蹤者是張志新(化名)和其女友劉穎贮懈,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體优训,經(jīng)...
    沈念sama閱讀 45,341評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡朵你,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,563評論 2 333
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了揣非。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片抡医。...
    茶點(diǎn)故事閱讀 39,731評論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖早敬,靈堂內(nèi)的尸體忽然破棺而出忌傻,到底是詐尸還是另有隱情,我是刑警寧澤搞监,帶...
    沈念sama閱讀 35,430評論 5 343
  • 正文 年R本政府宣布水孩,位于F島的核電站,受9級特大地震影響琐驴,放射性物質(zhì)發(fā)生泄漏俘种。R本人自食惡果不足惜秤标,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,036評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望宙刘。 院中可真熱鬧苍姜,春花似錦、人聲如沸悬包。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,676評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽布近。三九已至垫释,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間撑瞧,已是汗流浹背饶号。 一陣腳步聲響...
    開封第一講書人閱讀 32,829評論 1 269
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留季蚂,地道東北人茫船。 一個(gè)月前我還...
    沈念sama閱讀 47,743評論 2 368
  • 正文 我出身青樓,卻偏偏與公主長得像扭屁,于是被迫代替她去往敵國和親算谈。 傳聞我的和親對象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,629評論 2 354

推薦閱讀更多精彩內(nèi)容