zoukankan      html  css  js  c++  java
  • netty框架概述

    概述

    最近在学习netty的相关知识,也在看netty的源码,光看不练假把式,所以也正好利用自己学习的机会写几篇netty的分析文章,主要还是一些源码解析的文章,一方面有输出会促使自己在看源码,学习原理的过程中更系统,更深入,同时也能加强记忆,巩固对知识的理解。

    关于netty的简介和应用我就不做介绍了,在网络上都能搜索到相关的资料。

    netty是一个性能非常优秀的网络框架,采用reactor模式,使用非常高效的基于事件驱动的io线程模型,即经典的多路复用的io模式。关于io线程模型其实又是一个很大的话题,涉及到操作系统的底层原理,后面有时间我也打算深入学习一下这方面的知识,并写一些相关的分析文章。

    我的整体思路是这样的:首先,以netty提供给用户的常用的接口为切入点,一步步地深入netty内核进行分析,因为netty的模块众多,而且某一个层级往往有很多种平级的模块,这些不同的模块一般代表了不同的实现机制或不同的功能,如根据多路复用系统调用的不同就分为EpollEventLoop,NioEventloop,KQueueEventLoop等;根据不同的应用层协议把编解码器分为不同种类,如http,smtp, http2, xml等等。所以,我们只需要分析其中的一套,其他类型的在实际用到时在深入了解,这样既能整体上掌握框架,也能深入实现的细节。

    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)实际出发了一系列的初始化机制。

    总结

    本节,我主要是开了一个头,以spark中rpc服务端的初始化为例子切入netty的源码。

  • 相关阅读:
    杭电1058
    动态规划之背包模版
    按字典序依次打印只由1~n组成的n位数
    杭电1029
    杭电1257
    杭电2191
    杭电1114
    杭电2602
    南阳975
    杭电2138
  • 原文地址:https://www.cnblogs.com/zhuge134/p/11062266.html
Copyright © 2011-2022 走看看