《Netty學習打卡--從小白到放棄》----- 02 - 初識netty執行流程和重要組件

打卡日期(2019-07-03)

netty流程中涉及到的重要組件

  • channel:通道,相當於連接
  • channelHandler:通道處理器,類似於處理器,攔截器這樣的概念。當請求過來之後,會一個一個的通過channelHandler來得到一個個的處理器,處理之後交給業務方法完成真正的處理,然後按照相反的順序進行原路返回
  • pipeLine:管道,一個PipeLine是由多個channelHandler構成的。請求過來的時候,會通過一個個的處理器沿着管道不斷的往前走

結合例子來說明執行流程

package com.dragon.netty;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

/**
 * @Auther: lijianlong
 * @Date: 2019/7/3 17:44
 * @Description:
 */
public class Server {
    public static void main(String[] args) throws InterruptedException {

        //事件循環組 acceptorGroup用於接收請求
        EventLoopGroup acceptorGroup = new NioEventLoopGroup();

        //事件循環組 handlerGroup用於處理請求
        EventLoopGroup handlerGroup = new NioEventLoopGroup();
        try{
            // sub-class which allows easy bootstrap of  用於輕鬆的啓動bootstrap
            ServerBootstrap serverBootstrap = new ServerBootstrap()
                    // group (acceptorGroup,handlerGroup)
                    // acceptorGroup which is used for the parent (acceptor) 用於接收所有的請求
                    // handlerGroup are used to handle all the events and IO 處理所有的事件和IO操作
                    .group(acceptorGroup,handlerGroup)
                    // NioSctpServerChannel 利用nio模式接收一個新的連接創建NioSctpChannel
                    .channel(NioServerSocketChannel.class)
                    // 自定義處理器
                    .childHandler(new InitServer());
            //綁定80端口,端口號可以自定義
            ChannelFuture future = serverBootstrap.bind(80).sync();
            future.channel().closeFuture().sync();
        }finally {
            //友好關閉兩個線程組
            acceptorGroup.shutdownGracefully();
            handlerGroup.shutdownGracefully();
        }

    }
}
package com.dragon.netty;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.http.HttpServerCodec;


/**
 * @Auther: lijianlong
 * @Date: 2019/7/3 17:53
 * @Description:  初始化器
 */
public class InitServer extends ChannelInitializer<SocketChannel>{

    /**
     *  一旦channel管道被註冊這個方法就會被調用,這個方法返回一個之後實例將會從ChannelPipeline移除channel
     */
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        // 在次SocketChannel管道的位置增追加一個通道處理器
        ch.pipeline().addLast("httpServerCodec",new HttpServerCodec());
        // 在管道的最後一個位置追加自己的通道處理器
        ch.pipeline().addLast("myHandler",new MyHandler());
    }
}
package com.dragon.netty;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.handler.codec.http.*;
import io.netty.util.CharsetUtil;

/**
 * @Auther: lijianlong
 * @Date: 2019/7/3 18:05
 * @Description: 自定義處理器
 */
public class MyHandler extends SimpleChannelInboundHandler<HttpObject> {

    /**
     * <strong>這個方法將會在5.0中改名爲messageReceived
     * @param ctx           這個ChannelHandlerContext屬於 SimpleChannelInboundHandler處理器
     * @param msg           待處理的消息
     * @throws Exception    is thrown if an error occurred
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        if(msg instanceof HttpRequest){

            System.out.println("接收到一個請求");
            //向返回的內容
            ByteBuf context = Unpooled.copiedBuffer("Hello Word", CharsetUtil.UTF_8);
            //構造一個repsone
            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1,HttpResponseStatus.OK,context);
            response.headers()
                    // 設置返回類型
                    .set(HttpHeaderNames.CONTENT_TYPE,"text/plain")
                    // 設置返回多少字節 content-length
                    .set(HttpHeaderNames.CONTENT_LENGTH,context.readableBytes());

            // write 只會將返回信息寫入到緩存當中
            //ctx.write(response);
            //writeAndFlush 將消息寫入緩存併發送到客戶端之後清空緩存
            ctx.writeAndFlush(response);
        }
    }
}

在這裏插入圖片描述

啓動Server服務器:
通過瀏覽器訪問:http://localhost
響應:hello word

netty的執行流程

    結合上面的代碼梳理一下netty的執行流程

  • 1.創建ServerBootStrap實例
  • 2.設置並綁定Reactor線程池:EventLoopGroup,EventLoop就是處理所有註冊到本線程的多路複用器(Selector)上面的Channel
  • 3.設置並綁定服務端的Channel
  • 4.創建處理網絡事件的ChannelPipeLine和Handler,網絡事件以流的形式在其中流傳,handler完成多數的功能定製,比如編解碼等SSL安全認證
  • 5.綁定並啓動監聽端口
  • 6.當輪詢到準備就緒的Channel以後,由Reactor線程:NioEventLoop執行PipeLine中的方法,最終調用並執行channelHandler
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章