netty框架概述

概述

最近在學習netty的相關知識,也在看netty的源碼,光看不練假把式,因此也正好利用本身學習的機會寫幾篇netty的分析文章,主要仍是一些源碼解析的文章,一方面有輸出會促使本身在看源碼,學習原理的過程當中更系統,更深刻,同時也能增強記憶,鞏固對知識的理解。react

關於netty的簡介和應用我就不作介紹了,在網絡上都能搜索到相關的資料。bootstrap

netty是一個性能很是優秀的網絡框架,採用reactor模式,使用很是高效的基於事件驅動的io線程模型,即經典的多路複用的io模式。關於io線程模型其實又是一個很大的話題,涉及到操做系統的底層原理,後面有時間我也打算深刻學習一下這方面的知識,並寫一些相關的分析文章。網絡

個人總體思路是這樣的:首先,以netty提供給用戶的經常使用的接口爲切入點,一步步地深刻netty內核進行分析,由於netty的模塊衆多,並且某一個層級每每有不少種平級的模塊,這些不一樣的模塊通常表明了不一樣的實現機制或不一樣的功能,如根據多路複用系統調用的不一樣就分爲EpollEventLoop,NioEventloop,KQueueEventLoop等;根據不一樣的應用層協議把編解碼器分爲不一樣種類,如http,smtp, http2, xml等等。因此,咱們只須要分析其中的一套,其餘類型的在實際用到時在深刻了解,這樣既能總體上掌握框架,也能深刻實現的細節。app

 

netty應用示例

以前對spark-core的源碼進行過一些講解,分析了spark-core中的大部分模塊,可是其中有一個很重要的模塊卻沒有分析,那就是spark的rpc模塊,spark的rpc模塊是基於netty實現的,也是對netty的一個很典型的應用,因此這裏我仍是以spark中的rpc模塊爲示例,切入netty的源碼分析。框架

 1 // 初始化netty服務端
 2   private void init(String hostToBind, int portToBind) {
 3 
 4     // io模式,有兩種選項NIO, EPOLL
 5     IOMode ioMode = IOMode.valueOf(conf.ioMode());
 6     // 建立bossGroup和workerGroup,即主線程組合子線程組
 7     EventLoopGroup bossGroup =
 8       NettyUtils.createEventLoop(ioMode, conf.serverThreads(), conf.getModuleName() + "-server");
 9     EventLoopGroup workerGroup = bossGroup;
10 
11     // 緩衝分配器,分爲堆內存和直接內存
12     PooledByteBufAllocator allocator = NettyUtils.createPooledByteBufAllocator(
13       conf.preferDirectBufs(), true /* allowCache */, conf.serverThreads());
14 
15     // 建立一個netty服務端引導對象,並設置相關參數
16     bootstrap = new ServerBootstrap()
17       .group(bossGroup, workerGroup)
18       .channel(NettyUtils.getServerChannelClass(ioMode))
19       .option(ChannelOption.ALLOCATOR, allocator)
20       .childOption(ChannelOption.ALLOCATOR, allocator);
21 
22     // 內存使用的度量對象
23     this.metrics = new NettyMemoryMetrics(
24       allocator, conf.getModuleName() + "-server", conf);
25 
26     // 排隊的鏈接數
27     if (conf.backLog() > 0) {
28       bootstrap.option(ChannelOption.SO_BACKLOG, conf.backLog());
29     }
30 
31     // socket接收緩衝區大小
32     if (conf.receiveBuf() > 0) {
33       bootstrap.childOption(ChannelOption.SO_RCVBUF, conf.receiveBuf());
34     }
35 
36     // socket發送緩衝區大小
37     if (conf.sendBuf() > 0) {
38       bootstrap.childOption(ChannelOption.SO_SNDBUF, conf.sendBuf());
39     }
40 
41     // 子channel處理器
42     bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
43       @Override
44       protected void initChannel(SocketChannel ch) {
45         RpcHandler rpcHandler = appRpcHandler;
46         for (TransportServerBootstrap bootstrap : bootstraps) {
47           rpcHandler = bootstrap.doBootstrap(ch, rpcHandler);
48         }
49         context.initializePipeline(ch, rpcHandler);
50       }
51     });
52 
53     InetSocketAddress address = hostToBind == null ?
54         new InetSocketAddress(portToBind): new InetSocketAddress(hostToBind, portToBind);
55     // 綁定到ip地址和端口
56     channelFuture = bootstrap.bind(address);
57     // 同步等待綁定成功
58     channelFuture.syncUninterruptibly();
59 
60     port = ((InetSocketAddress) channelFuture.channel().localAddress()).getPort();
61     logger.debug("Shuffle server started on port: {}", port);
62   }

netty使用一個引導對象ServerBootstrap來引導服務端的啓動,最後的bootstrap.bind(address)實際出發了一系列的初始化機制。socket

總結

本節,我主要是開了一個頭,以spark中rpc服務端的初始化爲例子切入netty的源碼。ide

相關文章
相關標籤/搜索