Netty详解之二:Netty概述

总体上,Netty是一个高性能网络编程框架,不仅仅是对java socket接口的封装,它的功能可概括如下:

  • 事件驱动的异步编程模型(reactor模型)
  • 灵活的线程池管理;
  • 支持常见的传输层协议和应用层协议;
  • 屏蔽了底层bug(比如NIO Epoll Bug),更加稳定高效。

总之,netty性能较好,功能较全,文档相对完善,基本成为了java领域socket编程的首选工具。

Reactor模型

很多文章将Recactor模型和IO模型混在一起介绍,是不合适的;因为这二者不在同一个层次,reactor模型层次更高,它一般基于select io模型来实现。

Reactor模型核心思想是,是通过一个reactor来同时处理多个连接,并将事件分发给不同的工作线程(处理业务逻辑的线程)来处理。因此Reactor模型也可以叫做分发者模型。

Reactor模型有三种模式:单Reactor单线程,单Reactor多线程,主从Reactor多线程。本文不打算详解Reactor模型,建议大家看看《Scalable IO in Java》。

“主从Reactor多线程模式”几乎没有任何不可伸缩的瓶颈点,被Netty所支持,下面是该模式的图解:

reactor

上图有以下几个角色:

  • acceptor,处理连接请求的处理器,将新连接提交给subReactor;
  • mainReactor,负责监听,并调用acceptor来处理连接请求(mainReactor也可以使用线程池);
  • subReactor,处理socket连接的IO事件,并派发到对应线程来执行;
  • ThreadPool,工作线程池,为IO事件的处理提供线程支持;

Netty的结构

我们通过对照一段示例代码和上面Reactor模型结构图,来领会Netty的设计结构。

示例代码

这是一段极简的,使用Netty的server端模板式代码:

public class NettyServer {
    public static void main(String[] args) throws InterruptedException {
1        ServerBootstrap bootstrap = new ServerBootstrap();
2        NioEventLoopGroup bossGroup = new NioEventLoopGroup(1);
3        NioEventLoopGroup workerGroup = new NioEventLoopGroup(5);
4        bootstrap.group(bossGroup, workerGroup);
5        bootstrap.channel(NioServerSocketChannel.class);
6        bootstrap.childHandler(new ChannelInitializer<SocketChannel>() {
7            @Override
8            protected void initChannel(SocketChannel ch) {
9                ChannelPipeline pipeline = ch.pipeline();
10                pipeline.addLast(new NettyServerHandler());
11            }
12        });
13        ChannelFuture sync = bootstrap.bind(6667).sync();
14        sync.channel().closeFuture().sync();
    }
}
  • 行1:ServerBootstrap是Netty的启动引导类,负责将netty组件粘合起来,它的存在简化了netty程序编写;
  • 行2:NioEventLoopGroup可类比reactor,同时也是一个线程池,bossGroup扮演类似mainReactor的角色;
  • 行3:workerGroup扮演subReactor的角色;
  • 行4:bootStrap将bossGroup和childGroup结合起来;
  • 行5:bootstrap设定使用的Channel类型为NioServerSocketChannel,从名字上看与java nio对应;
    • Netty同样将socket连接抽象为Channel;
    • 由于Netty底层可以使用多种socket api,因此有多种Channel类型,对应java nio的是Nio(Server)SocketChannel
  • 行6:设定Channel对应的事件处理器,Channel处理器被抽象为ChannelHandler;
    • Netty采用事件驱动结构,所有的IO操作都作为事件被处理;
    • ChannelHandler作为事件处理器,对应reactor模型图中那些诸如**“decode,encode,compute”**的逻辑;
  • 行9:每个channel有一个ChannelPipeline
    • channel可能有很多ChannelHandler,pipeline将它们组织起来;
  • 行10:将一个handler加入到pipeline
  • 行13:绑定端口,sync是同步等待绑定成功的意思;
  • 行14:closeFuture也是一个ChannelFuture,等待关闭,使得主线程不退出;
    • ChannelFuture就是java Future的特化版本,netty异步化操作的工具。

再看一下NettyServerHandler的实现:

public class NettyServerHandler extends SimpleChannelInboundHandler<ByteBuf> {
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) {
        System.out.println("接受到客户端消息:" + msg.toString(StandardCharsets.UTF_8));
        ByteBuf byteBuf = ByteBufAllocator.DEFAULT.buffer(100).writeBytes("This is Netty Server\r\n".getBytes());
        ctx.writeAndFlush(byteBuf);
    }
}

NettyServerHandler的channelRead0回调在收到客户端的数据时被激活,ByteBuf是字节数据的包装类型,和java nio buffer有点类似。ChannelHandlerContext和pipline和channel都有关系,暂时不用完全理解,ctx.writeAndFlush向客户端发送数据。

此时,再看网上流传一张Netty架构图,会更清晰:

Netty架构

  • BossGroup和WorkerGroupd都是线程池
  • NioEventLoop是池内的单个线程
    • 之所以叫event loop,是因为它不断循环地检查并处理channel事件;
    • 当然还可以执行用户提交的异步任务(runAllTasks);
  • 最底下的Pipline包含一系列ChannelHandler,这些handler运行在eventLoop内。

Channel的多样性

Chanel是netty对一个通信通道的抽象,支持IO操作,可以看做底层socket链接的一个封装。通过Channel还可以获得链接的状态以及一些配置信息。

当一个连接建立时(发生在BossGroup),Netty创建一个Channel,并交给WorkGroup管理,WorkGroup会选定一个EventLoop为该Channel服务。Channel初始化过程需要绑定一个或多个ChannelHander,用来处理它的事件,这些handler组成一个Pipeline。该Pipeline运行在它所绑定的EventLoop内。

随传输层层协议的不同,有不同的Channel实现类:

  • NioSocketChannel:socket通信通道;
  • NioServerSocketChannel:服务端的socket监听通道;
  • NioDatagramChannel:UPD通道;
  • NioSctpChannel:Sctp通信通道;
  • NioSctpServerChannel:Sctp服务端监听通道;

即使传输层限定为TCP,不同的底层socket接口,也可能导致不同的Channel实现类:

  • NioSocketChannel:基于java封装的,平台无关的nio接口;
  • KQueueSocketChannel:Mac系统下,netty直接使用kqueue接口,从而提高效率;
  • EpollSocketChannel:linux系统下,netty直接使用epoll接口,从而提高效率;

Acceptor在哪?

由于接收socket连接请求的处理逻辑相对比较固定,基本不需要二次开发,所以Netty将它隐藏起来了,后续我们会将它挖掘出来。

可以提前透露,netty将acceptor自动装配为NioServerSocketChannel pipeline的头节点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值