最近中文字幕高清中文字幕无,亚洲欧美高清一区二区三区,一本色道无码道dvd在线观看 ,一个人看的www免费高清中文字幕

Netty 斷開(kāi)重連

1. 前言

上節(jié),我們主要講解了 Netty 的心跳檢測(cè)機(jī)制,其中核心目的是提高性能。本節(jié)我們主要講解的是 Netty 長(zhǎng)連接的穩(wěn)定性。

2. 學(xué)習(xí)目的

TCP 協(xié)議下,數(shù)據(jù)是可以雙向傳遞,其實(shí)也就是全雙工協(xié)議,通俗點(diǎn)來(lái)說(shuō)就是長(zhǎng)連接,只要客戶(hù)端和服務(wù)端連接之后,雙方可以正常通行,那么長(zhǎng)連接是否存在什么不穩(wěn)定性呢?

在長(zhǎng)連接情況下,通常面臨的情況就是網(wǎng)絡(luò)問(wèn)題,網(wǎng)絡(luò)抖動(dòng)造成的連接假死,舉個(gè)例子:其實(shí)客戶(hù)端和服務(wù)端的 TCP 連接已經(jīng)斷開(kāi),但是雙方?jīng)]有監(jiān)聽(tīng)到,認(rèn)為該連接仍然是有效的。

這樣的問(wèn)題會(huì)導(dǎo)致以下幾個(gè)后果,如下所示:

  1. 客戶(hù)端往服務(wù)端發(fā)送消息時(shí),由于連接已經(jīng)斷開(kāi),會(huì)導(dǎo)致請(qǐng)求超時(shí),影響用戶(hù)體驗(yàn);
  2. 服務(wù)端往客戶(hù)端推送消息時(shí),由于連接已經(jīng)斷開(kāi),導(dǎo)致連接推送失?。?/li>
  3. 每條連接都消耗 cpu 和內(nèi)存資源,大量的假死會(huì)導(dǎo)致服務(wù)器資源消耗,導(dǎo)致服務(wù)器卡頓甚至宕機(jī)。

3. 連接面臨問(wèn)題及解決方案

圖片描述

4. 連接假死

4.1 產(chǎn)生的原因

連接已經(jīng)斷開(kāi),但是程序沒(méi)有捕捉的到,認(rèn)為連接還存在,產(chǎn)生的原因大致如下:

  1. 應(yīng)用程序內(nèi)部線(xiàn)程堵塞,導(dǎo)致數(shù)據(jù)讀寫(xiě)也會(huì)堵塞;
  2. 網(wǎng)絡(luò)抖動(dòng),數(shù)據(jù)丟包等,發(fā)送方一種發(fā)送不出數(shù)據(jù),接收方也收不到數(shù)據(jù),連接就一直的耗著;
  3. 公網(wǎng)相對(duì)內(nèi)網(wǎng)來(lái)說(shuō)不是很穩(wěn)定,受到的干擾更多,故障的概率也會(huì)增大。

4.2 解決辦法

問(wèn)題: 服務(wù)端 5 秒鐘沒(méi)用讀取數(shù)據(jù)事件,那么是否一定是假死呢?

回答: 不一定,主要有兩種情況,①連接假死;②連接空閑。

針對(duì)連接假死的解決方案

主要是通過(guò)心跳檢測(cè)去監(jiān)控,如果指定時(shí)間之內(nèi),服務(wù)端沒(méi)有收到客戶(hù)端的數(shù)據(jù),則主動(dòng)斷開(kāi)連接,杜絕了連接假死現(xiàn)象。

針對(duì)連接空閑狀態(tài)的解決方案

情況一: 如果對(duì)通信的實(shí)時(shí)性要求不高,并且對(duì)性能要求很高的情況,可以直接斷開(kāi)連接,等待有需要的時(shí)候,再重新連接(這個(gè)是上節(jié)已經(jīng)講解過(guò)了,適合客戶(hù)端主動(dòng)的業(yè)務(wù)場(chǎng)景,比如:IM);
情況二: 如果對(duì)通信的實(shí)時(shí)性要求很高,則不能斷開(kāi)連接(比如:消息推送),為了保證連接能夠存活而不被心跳檢測(cè)機(jī)制自動(dòng)斷開(kāi)。

針對(duì)情況二的解決方案如下:

  1. 定時(shí)發(fā)送空包,并且時(shí)間間隔小于心跳檢測(cè)時(shí)間間隔,保證連接存活;
  2. 如果連接真的斷開(kāi)了,則客戶(hù)端監(jiān)聽(tīng)事件 channelInactive () 里面實(shí)現(xiàn)斷開(kāi)重連;

總結(jié),這種模式的好處有兩點(diǎn),①保證連接能夠長(zhǎng)時(shí)間存活,避免錯(cuò)過(guò)重要消息;②避免連接空閑時(shí),頻繁的斷開(kāi)和重連,浪費(fèi)資源。

其中,心跳檢測(cè)上節(jié)以及詳細(xì)講解了,這里主要講解一下發(fā)送空包數(shù)據(jù)和斷開(kāi)重連如何實(shí)現(xiàn)。

5. 代碼實(shí)現(xiàn)

5.1 服務(wù)端心跳檢測(cè)

實(shí)例:

ChannelPipeline pipeline = ch.pipeline();
//5秒鐘之內(nèi)沒(méi)有 讀事件 則斷開(kāi)連接
pipeline.addLast(new ReadTimeoutHandler(5, TimeUnit.SECONDS));

//字符串解碼器
pipeline.addLast(new StringDecoder());

//字符串編碼器
pipeline.addLast(new StringEncoder());

//業(yè)務(wù)Handler
pipeline.addLast(new HeartBeatHandler());

代碼說(shuō)明:

服務(wù)端主要是監(jiān)聽(tīng)讀事件,每隔 5 秒讀取不到數(shù)據(jù),則認(rèn)為連接無(wú)效,主動(dòng)斷開(kāi)連接。

5.2 客戶(hù)端定時(shí)發(fā)送空包

實(shí)例:

public class HeartBeatTimerHandler extends ChannelInboundHandlerAdapter {
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //發(fā)送空包
        scheduleSendHeartBeat(ctx);
    }

    private void scheduleSendHeartBeat(ChannelHandlerContext ctx) {
        ctx.executor().schedule(() -> {
            if (ctx.channel().isActive()) {
                //發(fā)送空包(定義一個(gè)實(shí)體)
                ctx.writeAndFlush(Unpooled.EMPTY_BUFFER);
            }

        }, 3, TimeUnit.SECONDS);
    }
}

代碼說(shuō)明:

  1. 借助 EventLoop 的定時(shí)線(xiàn)程池去實(shí)現(xiàn)每隔 3 秒鐘發(fā)送一個(gè)空包;
  2. 空包數(shù)據(jù),自定義一個(gè)實(shí)體即可;
  3. 主要的是空包的時(shí)間間隔(3s)一定要小于心跳監(jiān)聽(tīng)的時(shí)間間隔(5s)。

5.3 客戶(hù)端斷開(kāi)重連

實(shí)例:

//字符串解碼器
pipeline.addLast(new StringDecoder());
//字符串編碼器
pipeline.addLast(new StringEncoder());
//業(yè)務(wù)Handler,需要傳遞“bootstrap”
pipeline.addLast(new ClientHandler(bootstrap));
public class ClientHandler extends ChannelInboundHandlerAdapter {
    private Bootstrap bootstrap;
    ClientHandler(Bootstrap bootstrap){
        this.bootstrap=bootstrap;
    }
	
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
		bootstrap.connect("127.0.0.1",80).sync();
    }
}

代碼說(shuō)明:

  1. 連接斷開(kāi)時(shí),客戶(hù)端的 Handler 的 channelInactive () 會(huì)監(jiān)聽(tīng)的到,在該方法里面實(shí)現(xiàn)斷開(kāi)重連;
  2. Handler 必須傳遞 bootstrap。

6. 小結(jié)

本節(jié)主要講解了基于心跳檢測(cè)的基礎(chǔ)上實(shí)現(xiàn)了空包發(fā)送和斷開(kāi)重連的功能,主要核心意圖有兩個(gè)

  1. 空包發(fā)送: 讓連接能夠長(zhǎng)時(shí)間的存活,而避免空閑連接收到心跳檢測(cè)的干擾;同時(shí)還避免了心跳檢測(cè)導(dǎo)致的頻繁的斷開(kāi)和重連,導(dǎo)致資源浪費(fèi);
  2. 斷開(kāi)重連: 讓連接一直在線(xiàn),保證了連接的穩(wěn)定性。