Netty回調(diào)與Channel執(zhí)行流程分析

我們用Netty搭建一個簡單的http服務(wù)器省核,來簡單的分析一個Channel的執(zhí)行流程。
我們來新建一個Server

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;

public class TestServer {
    public static void main(String[] args) throws Exception{
        /**
         * 死循環(huán) 線程組
         * NioEventLoopGroup 是用來處理I/O操作的線程池蕴侧,Netty對 EventLoopGroup 接口針對不同的傳輸協(xié)議提供了不同的實現(xiàn)逐抑。
         * 在本例子中瞒爬,需要實例化兩個NioEventLoopGroup羔挡,通常第一個稱為“boss”,
         * 用來accept客戶端連接,另一個稱為“worker”匹颤,處理客戶端數(shù)據(jù)的讀寫操作。
         */
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try{
            //啟動服務(wù)端的類 ServerBootstrap 是啟動服務(wù)的輔助類托猩,有關(guān)socket的參數(shù)可以通過ServerBootstrap進(jìn)行設(shè)置印蓖。
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup, workerGroup)
                    .channel(NioServerSocketChannel.class)//這里指定NioServerSocketChannel類初始化channel用來接受客戶端請求。
                    .childHandler(new TestServerInitializer());
            ChannelFuture channelFuture = serverBootstrap.bind(8899).sync();
            channelFuture.channel().closeFuture().sync();
        }finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

}

建一個Initializer

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

//通常會為新SocketChannel通過添加一些handler京腥,來設(shè)置ChannelPipeline赦肃。
public class TestServerInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        pipeline.addLast("httpServiceCodec",new HttpServerCodec());//netty自己的處理器
        pipeline.addLast("testHttpServerHandler",new TestHttpServerHandler());//自定義的處理器
    }
}

自定義一個Handler


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;

import java.net.URI;

public class TestHttpServerHandler extends SimpleChannelInboundHandler<HttpObject> {
    /**
     * SpringMVC由容器來判斷http請求是否結(jié)束了 netty可以自己判斷keepalive
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, HttpObject msg) throws Exception {
        System.out.println(msg.getClass());
        System.out.println(ctx.channel().remoteAddress());
//        Thread.sleep(8000);
        if (msg instanceof HttpRequest) {
            HttpRequest httpRequest = (HttpRequest) msg;

            System.out.println("請求方法名:" + httpRequest.method().name());
            URI uri = new URI(httpRequest.uri());
            if ("/favicon.ico".equals(uri.getPath())) {
                System.out.println("請求favicon.ico");
                return;
            }

            //讀取客戶端的請求并返回響應(yīng)
            ByteBuf content = Unpooled.copiedBuffer("Hello World", CharsetUtil.UTF_8);

            FullHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, content);
            response.headers().set(HttpHeaderNames.CONTENT_TYPE, "text/plain");
            response.headers().set(HttpHeaderNames.CONTENT_LENGTH, content.readableBytes());

            ctx.writeAndFlush(response);
            ctx.channel().close();
        }
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channerl active");
        super.channelActive(ctx);
    }

    @Override
    public void channelRegistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelRegistered");
        super.channelRegistered(ctx);
    }

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        System.out.println("handlerAdded");
        super.handlerAdded(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelInactive");
        super.channelInactive(ctx);
    }

    @Override
    public void channelUnregistered(ChannelHandlerContext ctx) throws Exception {
        System.out.println("channelUnregistered");
        super.channelUnregistered(ctx);
    }
}

curl 'http://localhost:8899'

handlerAdded 一個新的handler添加 新的通道
channelRegistered  注冊到某個對象
channerl active  連接處于活動狀態(tài)
class io.netty.handler.codec.http.DefaultHttpRequest
/0:0:0:0:0:0:0:1:60290
請求方法名:GET  請求讀取
class io.netty.handler.codec.http.LastHttpContent$1
/0:0:0:0:0:0:0:1:60290
channelInactive     變成不活動狀態(tài)
channelUnregistered 取消注冊

如果使用瀏覽器來請求 http://localhost:8899 則有所不同

handlerAdded
channelRegistered
channerl active
class io.netty.handler.codec.http.DefaultHttpRequest
/0:0:0:0:0:0:0:1:60322
請求方法名:GET
class io.netty.handler.codec.http.LastHttpContent$1
/0:0:0:0:0:0:0:1:60322
class io.netty.handler.codec.http.DefaultHttpRequest
/0:0:0:0:0:0:0:1:60322
請求方法名:GET
請求favicon.ico
class io.netty.handler.codec.http.LastHttpContent$1
/0:0:0:0:0:0:0:1:60322

可以看到并沒有出現(xiàn)

channelInactive
channelUnregistered

當(dāng)我們把瀏覽器關(guān)閉之后,這兩行才出現(xiàn)公浪,這里也體現(xiàn)了Netty并沒有遵循Servlet規(guī)范他宛,需要自己實現(xiàn)。
我們平時的SpringMVC應(yīng)用運行在tomcat之上欠气,與http請求之間的連接由tomcat來保證相應(yīng)的連接斷掉厅各,但是Netty不是這樣的。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末预柒,一起剝皮案震驚了整個濱河市队塘,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌宜鸯,老刑警劉巖憔古,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異顾翼,居然都是意外死亡投放,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進(jìn)店門适贸,熙熙樓的掌柜王于貴愁眉苦臉地迎上來灸芳,“玉大人涝桅,你說我怎么就攤上這事±友” “怎么了冯遂?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長谒获。 經(jīng)常有香客問我蛤肌,道長,這世上最難降的妖魔是什么批狱? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任裸准,我火速辦了婚禮,結(jié)果婚禮上赔硫,老公的妹妹穿的比我還像新娘炒俱。我一直安慰自己,他們只是感情好爪膊,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布权悟。 她就那樣靜靜地躺著,像睡著了一般推盛。 火紅的嫁衣襯著肌膚如雪峦阁。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天耘成,我揣著相機與錄音榔昔,去河邊找鬼。 笑死凿跳,一個胖子當(dāng)著我的面吹牛件豌,可吹牛的內(nèi)容都是我干的疮方。 我是一名探鬼主播控嗜,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼骡显!你這毒婦竟也來了疆栏?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤惫谤,失蹤者是張志新(化名)和其女友劉穎壁顶,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體溜歪,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡若专,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了蝴猪。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片调衰。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡膊爪,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出嚎莉,到底是詐尸還是另有隱情米酬,我是刑警寧澤,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布趋箩,位于F島的核電站赃额,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏叫确。R本人自食惡果不足惜跳芳,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望竹勉。 院中可真熱鬧筛严,春花似錦、人聲如沸饶米。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽檬输。三九已至照瘾,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間丧慈,已是汗流浹背析命。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留逃默,地道東北人鹃愤。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像完域,于是被迫代替她去往敵國和親软吐。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

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

  • Spring Boot 參考指南 介紹 轉(zhuǎn)載自:https://www.gitbook.com/book/qbgb...
    毛宇鵬閱讀 46,844評論 6 342
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理吟税,服務(wù)發(fā)現(xiàn)凹耙,斷路器,智...
    卡卡羅2017閱讀 134,695評論 18 139
  • 從三月份找實習(xí)到現(xiàn)在肠仪,面了一些公司肖抱,掛了不少,但最終還是拿到小米异旧、百度意述、阿里、京東、新浪荤崇、CVTE镐依、樂視家的研發(fā)崗...
    時芥藍(lán)閱讀 42,272評論 11 349
  • 最棒的情人節(jié)文喜每!
    冰清玉潔小玉兒閱讀 220評論 0 0
  • 你很不舒服嗎务唐? 有點。 為什么带兜? 心里堵的慌枫笛。 為什么? 我感覺我好像在做自己不喜歡的事情刚照。 為什么刑巧? 因為我要堅...
    騰_飛閱讀 204評論 0 0