Netty組件和設(shè)計(jì)

通過Netty入門,可以運(yùn)行和啟動(dòng)一個(gè)簡單的客戶端和服務(wù)端的應(yīng)用了,這里看下Netty每個(gè)組件的細(xì)節(jié),以及組件之前是如何協(xié)作的。

實(shí)例

我們先看代碼:注釋中包含了使用Netty服務(wù)端的一些操作說明,剛學(xué)的時(shí)候不太明白這些東西的意思,但是看了Netty的組件設(shè)計(jì),及其架構(gòu),就容易理解每個(gè)語句對應(yīng)的意思。

 public void run() throws Exception {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            // 服務(wù)端的BootStrap,一個(gè)需要接受連接,一個(gè)用來處理事件
            b.group(bossGroup, workerGroup)
                    // Channel理解為通道,網(wǎng)絡(luò)傳輸?shù)耐ǖ李愋?                    .channel(NioServerSocketChannel.class)

                    // ChannerlHandler要被裝進(jìn)ChannelPipeline
                    // 而過程則是調(diào)用ChannelInitializer的iniChannel方法
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch)
                                throws Exception {
                            // addLast,在PipeLine中的Handler是有順序的,所以
                            // 有addLast,addFirst等方法
                            // 添加的同時(shí),可以指定Encoder和Decoder
                            ch.pipeline().addLast(new RequestDecoder(),
                                    new ResponseDataEncoder(),
                                    new ProcessingHandler());
                        }
                    }).option(ChannelOption.SO_BACKLOG, 128)
                    .childOption(ChannelOption.SO_KEEPALIVE, true);
            
            // TODO 待細(xì)看,先當(dāng)做固定的寫法
            ChannelFuture f = b.bind(port).sync();
            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
            bossGroup.shutdownGracefully();
        }
    }

客戶端與服務(wù)端基本一致,只是將綁定本地端口換成了連接遠(yuǎn)端的端口

EventLoopGroup workerGroup = new NioEventLoopGroup();

        try {
            Bootstrap b = new Bootstrap();
            b.group(workerGroup)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.SO_KEEPALIVE, true)
                    // 配置ChannelHandler
                    .handler(new ChannelInitializer<SocketChannel>() {

                        @Override
                        public void initChannel(SocketChannel ch)
                                throws Exception {
                            ch.pipeline().addLast(new RequestDataEncoder(),
                                    new ResponseDataDecoder(), new ClientHandler());
                        }
                    });

            ChannelFuture f = b.connect(host, port).sync();

            f.channel().closeFuture().sync();
        } finally {
            workerGroup.shutdownGracefully();
        }

下面是看Netty In Action一書中整理到的其組件設(shè)計(jì)的一些知識(shí)點(diǎn)。

Netty網(wǎng)絡(luò)層

Channel,EventLoop,ChannelFuture可以看做Netty的網(wǎng)絡(luò)抽象層

  • Channel - Socket
  • EventLoop - 控制流,多線程,并發(fā)
  • ChannelFuture - 異步通知
Channel接口

基礎(chǔ)的IO操作,bind,connect,read,write. 在底層上,這些主要依賴Java的Socket,Netty的Channel封裝了底層的復(fù)雜操作。使得用起來簡化很多,它提供了很多預(yù)定義的特定場景下的實(shí)現(xiàn)。

image.png
EventLoop接口

EventLoop接口定義了連接的整個(gè)生命周期中的事件處理,下圖解釋了Channel,EventLoop,Threads和EventLoopGroup的關(guān)系

image.png
  • EventLoopGroup包含一個(gè)或多個(gè)EventLoop
  • EventLoop的整個(gè)生命周期與單個(gè)線程的生命周期一致
  • Channel注冊它的生命周期到單個(gè)的EventLoop上
  • 單個(gè)EventLoop能分配一個(gè)或多個(gè)Channel
  • 所有的I/O事件被EventLoop處理
ChannelFuture

在Netty中,所有的IO操作都是異步的,因?yàn)椴僮鞑皇橇⒖谭祷亟Y(jié)果,我們需要一個(gè)方式在程序執(zhí)行一會(huì)再獲取結(jié)果。Netty提供了ChannelListener,它的addListner方法注冊一個(gè)ChannelFutureListener,當(dāng)操作完成的時(shí)候就會(huì)通知Listener。

ChannelHandler and ChannelPipeline

這兩個(gè)組件用來管理數(shù)據(jù)流和執(zhí)行應(yīng)用的邏輯。

ChannelHandler

從開發(fā)者的角度來看,Netty最主要的組件就是ChannelHandler,它可以處理應(yīng)用內(nèi)輸入和輸出的數(shù)據(jù)流,基本上可以做任意類型的數(shù)據(jù)操作,例如數(shù)據(jù)格式轉(zhuǎn)換,或者異常處理。

ChannelPipeline

ChannelPipeline提供了ChannelHandler的容器,其內(nèi)部可以有多個(gè)ChannelHandler,定義了鏈?zhǔn)紺hannelHandler傳播輸入數(shù)據(jù)和輸出數(shù)據(jù)流的API。當(dāng)Channel被創(chuàng)建的時(shí)候,它會(huì)自動(dòng)的分配到ChannelPipeline。

  • ChannelInitializer的實(shí)現(xiàn)被注冊到ServerBootstrap
  • 當(dāng)ChannelInitializer.initChannel被調(diào)用,就將多個(gè)ChannelHandler安裝到pipeline中
  • ChannelInitializer將自己從ChannelPipeline中移除

ChannelHandler可以看做是代碼的容器,里面主要都是我們的程序邏輯,處理事件還有在ChannelPipeline中的數(shù)據(jù),ChannelHandler主要被添加進(jìn)ChannelPipeLine中,當(dāng)它被添加的時(shí)候會(huì)被分配一個(gè)ChannelHandlerContext。

小結(jié)

這里主要介紹了Netty的一些基本組件。

參考

  • 《Netty in Action》
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容