Netty由淺到深_第五章_Netty心跳檢測機制案例

應用實例-羣聊系統

  • 1)編寫一個Netty心跳檢測機制案例,當服務器超過3秒沒有讀取時,就會提示空閒
  • 2)當服務器超過5秒沒有寫操作時,就表示空閒
  • 3)實現當服務器超過7秒沒有都或者寫操作時,就提示讀寫空閒
package com.dd.netty.heartbeat;

import com.dd.netty.groupchat.GroupChatServer;
import com.dd.netty.groupchat.GroupChatServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;

import java.util.concurrent.TimeUnit;

public class MyServer {

    private int port ;//監聽端口

    public MyServer(int port){
        this.port = port;
    }

    public void run() throws InterruptedException {
    //創建bossGroup和WrokerGroup
    NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
    NioEventLoopGroup workerGroup = new NioEventLoopGroup();//默認cpu核數乘以2個NioEventLoop
        try {
        ServerBootstrap bootstrap = new ServerBootstrap();
        bootstrap.group(bossGroup,workerGroup)
                .channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.INFO))//在boosGroup 增加一個日誌處理器
                .option(ChannelOption.SO_BACKLOG,128)
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    @Override
                    protected void initChannel(SocketChannel socketChannel) throws Exception {

                        ChannelPipeline pipeline = socketChannel.pipeline();

                        //加入Netty 提供的 IdleStateHandler
                        /*
                        * long readerIdleTime, 表示多長時間服務端沒有讀取客戶端數據。就會發送一個心跳檢測包,檢測是否還是連接的狀態
                        * long writerIdleTime,表示多長時間服務端沒有寫數據給客戶端數據。就會發送一個心跳檢測包,檢測是否還是連接的狀態
                        *  long allIdleTime, 表示多長時間服務端既沒有寫數據又沒有讀取數據給客戶端數據。就會發送一個心跳檢測包,檢測是否還是連接的狀態
                        * TimeUnit unit
                        *當IdleStateEvent事件觸發後,就會傳遞給管道的下一個handler去處理,通過調用下一個handler的userEventTiggered方法處理
                        * IdleStateEvent(都空閒,寫空閒,讀寫空閒)
                        * */
                        pipeline.addLast(new IdleStateHandler(3,5,7, TimeUnit.SECONDS));

                        //加入一個對空閒檢測進一步處理的自定義handler
                        pipeline.addLast(new MyServerHandler());
                    }
                });

        System.out.println("Netty服務器啓動");

        ChannelFuture chanelFuture = bootstrap.bind(port).sync();

        //監聽關閉事件
        chanelFuture.channel().closeFuture().sync();
    }finally {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}


    public static void main(String[] args) throws InterruptedException {
        new MyServer(7000).run();
    }
}

package com.dd.netty.heartbeat;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.handler.timeout.IdleStateEvent;

public class MyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     *
     * @param ctx 上下文
     * @param evt 事件
     * @throws Exception
     */
    @Override
    public void userEventTriggered(ChannelHandlerContext ctx, Object evt) throws Exception {
        if (evt instanceof IdleStateEvent){

            //將evt向下轉型到IdleStateEvent

            IdleStateEvent event = (IdleStateEvent)evt;

            String eventType =null;
            switch (event.state()){
                case READER_IDLE:
                    eventType = "讀空閒";
                    break;
                case ALL_IDLE:
                    eventType="讀寫空閒";
                    break;
                case WRITER_IDLE:
                    eventType="寫空閒";
                    break;
            }

            System.out.println(ctx.channel().remoteAddress()+"--超時事件--"+eventType);
            //接下來做相應處理

            //假如發生心跳事件  我們關閉通道  那麼只會產生一次心跳
        }
    }
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章