1. 程式人生 > >Netty 執行流程分析與重要元件介紹

Netty 執行流程分析與重要元件介紹

Netty的應用場景:

1、Netty可以作為RBC的通訊框架或是通訊的協議、通訊的庫,實現了遠端過程的呼叫,是基於socket的方式。這是在Netty開發裡面很大的應用場景。

2、Netty可以作為長連線的伺服器,就是基於websocket的長連線伺服器,實現伺服器與客戶端之間的長連線的通訊。

3、Netty還可以作為HTTP的伺服器,類似於Tomcat 等servlet容器。但是當它充當HTTP伺服器的時候,它的程式設計模型、獲取請求的引數等並不是基於servlet規範的。可以通過瀏覽器去訪問的。

一、使用者向伺服器傳送請求,伺服器返回一個helloworld的情景 (第三種應用場景)

1、channel :通道,相當於一個連線

2、channelHandler:通道的處理器,類似於處理器、攔截器這樣的概念。請求過來之後,會一個一個的通過channelHandler來得到一個一個的處理,處理之後交給業務方法完成真正的處理,然後按照相反的順序進行原路的返回

3、pipeline:管道。一個 pipeline是由多個channelHandler 構成的,構成管道的形式。請求過來的時候,會通過一個一個的處理器沿著管道不斷的往前走

程式碼:本人建立的是gradel的專案

①、build.gradle

plugins {
    id 'java'
}

group 'com.cxm'
version '1.0-SNAPSHOT'

sourceCompatibility = 1.8
targetCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {

    compile group: 'io.netty', name: 'netty-all', version: '4.1.29.Final'

}

②、TestServer

package com.cxm.netty.firstexample;

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;

/**
 * @Date: 2018/10/16 15:35
 * @Description: 伺服器啟動程式碼
 */
public class TestServer {

    public static void main(String[] args) throws Exception{

        //定義兩個事件迴圈組 (兩個執行緒組)
        //NioEventLoopGroup()可以理解為死迴圈。不斷的接受客戶端發起的連線,連線進來之後對連線進行處理,緊接著迴圈繼續執行
        // boosGroup --》執行緒組不斷的從客戶端那邊接受連線,但是不對連線做任何的處理,直接傳給worker
        // workerGroup --》執行緒組接收到boosGroup傳過來的連線,真正的完成對連線的處理。例如獲取連線的引數,進行實際的業務處理,把結果返回給客戶端
        EventLoopGroup boosGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();

       try{
           //ServerBootstrap 服務端啟動,他實際上是一個比較方便的輕鬆的啟動服務端的類
           ServerBootstrap serverBootstrap = new ServerBootstrap();
           // childHandler 子處理器 自己編寫的處理器,請求到來時,有我們編寫的處理器進行處理。
           serverBootstrap.group(boosGroup,workerGroup).channel(NioServerSocketChannel.class).childHandler(new TestServerInitializer());

           ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
           channelFuture.channel().closeFuture().sync();
       }finally {
           //優雅的關閉
           boosGroup.shutdownGracefully();
           workerGroup.shutdownGracefully();
       }
    }
}

③、TestServerInitializer

package com.cxm.netty.firstexample;

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

/**
 * @Date: 2018/10/16 16:00
 * @Description: 初始化器
 */
public class TestServerInitializer extends ChannelInitializer<SocketChannel> {

    //連線被建立之後會立刻執行 initChannel 回撥方法
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        //pipeline 是 根據業務請求完成處理
        ChannelPipeline pipeline = ch.pipeline();

        //在最後新增 自定義的若干個處理器
        pipeline.addLast("httpServerCodec ",new HttpServerCodec());
        //新增自定義的處理器
        pipeline.addLast("testHttpServerHandler",new TestHttpServerHandler());
    }
}

④、TestHttpServerHandler

package com.cxm.netty.firstexample;

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;

/**
 * @Date: 2018/10/16 16:08
 * @Description: 定義自己的處理器
 */
public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {

    //channelRead0 ---》 讀取客戶端傳送過來真正的請求,並且向客戶端返回響應
    //相當於 messageReceived
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {

        if (msg instanceof HttpRequest){

            //構造響應的字串
            ByteBuf byteBuffer = Unpooled.copiedBuffer("Hello World" , CharsetUtil.UTF_8);

            //構造響應
            FullHttpResponse response =new DefaultFullHttpResponse(HttpVersion.HTTP_1_1 , HttpResponseStatus.OK,content);

            //設定 Response 頭資訊
            response.headers().set(HttpHeaderNames.CONTENT_TYPE,"text_plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH,content.readableBytes());

            //返回給客戶端的response物件
            ctx.writeAndFlush(response);
        }
    }
}

執行:

執行TestServer,  Linux開啟  curl 'http://localhost:8899';就會出現 

執行流程:


1、首先會啟動 Bootstrap 伺服器,伺服器裡面會關聯兩個事件迴圈組(boosGroup,workerGroup)
2、在伺服器啟動的時候呢,會關聯一個相應的處理器childHandler
3、在childHandler 裡面定義的處理器 TestServerInitializer ,回撥方法裡面定義的若干個自定義的處理器,
也可以定義Netty本身內建的ChannelHandler,按照順序往下走,
最終會走到我們自己提供的一個處理器TestHttpServerHandler,然後返回結果給客戶端。

以上就是最基本的入門程式!! 

用網站來請求,他會請求你網站的圖示,就如圖的 favicon.ico