牛掰!鹅厂大佬首推的Netty高并发手册,带你将知识点一网打尽

480 阅读4分钟

Hello,今天给各位童鞋们分享Netty,赶紧拿出小本子记下来吧!

image.png

一、Netty简介

Netty是一个异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。

二、为什么使用Netty

2.1、手写Java NIO的缺点

因为自己写Java NIO很麻烦:

1)NIO类库和API复杂,要熟练掌握Selector, ServerSocketChannel, SocketChannel, ByteBuffer等

2)要熟悉Java多线程编程,且涉及到Reactor模式,这样才能写出高质量的NIO程序

3)臭名昭著的epoll bug,它会导致selector空轮询,最终导致CPU 100%。

2.2、Netty的优点

1)API使用简单,学习成本低

2)很多功能封装好了,如编解码、支持多种协议如PB

3)性能高:相比其他NIO框架,netty性能最优

4)社区活跃

5)Dubbo, ES,RocketMQ, GRPC等都采用了Netty,质量得到验证。

三、Netty架构图

image.png

上图为netty官网首页的架构图:

1)绿色部分是Core核心模块,包括零拷贝、API库、可扩展事件模型等

2)橙色部分:协议支持,包括http协议、webSocket、SSL、Protocol buffer, zlib/gzip压缩与解压缩,Large File Transfer大文件传输等。

3)红色部分为传输服务,包括Socket, Datagram, Http Tunnel等

从上图可以看出netty都有什么功能了:它的功能、协议、传输方式支持的都比较全。

四、Netty的使用

image.png

4.1、引入maven依赖

<groupId>io.netty</groupId>

<artifactId>netty-all</artifactId>

<version>4.1.20.Final</version>

4.2、创建服务端启动类

image.png

4.3、创建服务端业务处理器Handler

image.png

4.4、创建客户端启动类

image.png

4.5、创建客户端业务处理器Handler

image.png

五、Netty的特性与重要组件

5.1、taskQueue任务队列

如果Handler处理器有一些长时间的业务处理,可以交给taskQueue异步处理,按下面的方式来通过taskQueue做业务处理:

image.png 总结:这就解释了上一篇reactor中的问题,在handler监听到workGroup中的事件后,实际上也放到了taskQueue线程池中做了异步处理。

5.2、scheduleTaskQueue延时任务队列

延迟任务队列,除了handler处理异步外,只是多了等一段时间在执行:

ctx.channel().eventLoop().schedule(new Runnable() {

@Override

public void run() {

    try {

        //长时间操作,不至于长时间的业务操作导致Handler阻塞

        Thread.sleep(1000);

        System.out.println("长时间的业务处理");

    } catch (Exception e) {

        e.printStackTrace();

    }

}

},5, TimeUnit.SECONDS);//5秒后执行

5.3、Future异步机制

在客户端启动时,有这样一行代码:

//连接服务端

        ChannelFuture channelFuture = bootstrap.connect("127.0.0.1", 6666).sync();

ChannelFuture提供了操作完成后,一种异步通知方式。在Socket编程中,响应结果都是阻塞的,而ChannelFuture则采用观察者模式异步返回结果:

image.png

5.4、Bootstrap与ServerBootStrap

Bootstrap和ServerBootStrep是netty提供的创建客户端和服务端启动的工厂类,使用这个工厂类非常便利地创建启动类:

image.png

通过Bootstrap创建启动器的步骤为

image.png

5.4.1、group()

在Reactor模式文章中,我们知道服务端要用到两个线程组:

1)bossGroup:用于监听客户端连接,专门负责与客户端创建连接,并把连接注册到WorkGroup的Selector中

2)workGroup:用于处理每一个连接发生的读写事件

一般创建线程直接使用以下new就可以了:

EventLoopGroup bossGroup = new NioEventLoopGroup();

EventLoopGroup workerGroup = new NioEventLoopGroup();

那么,既然是线程组,线程数默认多少呢?看源码:

image.png 从源码可以看到,默认线程数是CPU核数的2倍。如果想自定义线程数,可以使用有参构造器:

//设置bossGroup线程数为1

EventLoopGroup bossGroup = new NioEventLoopGroup(1);

//设置workerGroup线程数为16

EventLoopGroup workerGroup = new NioEventLoopGroup(16);v

5.4.2、channel()

channel() 方法用于设置通道类型,当建立连接后,会根据这个设置创建对应的Channel实例:

image.png 通道的类型有以下几种:

1)NioSocketChannel:异步非阻塞的客户端TCP Socket连接

2)NioServerSocketChannel:异步非阻塞的服务端TCP Socket连接

备注:常用的就是这两种通道类型,因为他们异步非阻塞

3)OioSocketChannel:同步阻塞的客户端TCP Socket连接

4)OioServerSocketChannel:同步阻塞的服务端TCP Socket连接

5.4.3、option() 与 childOption()

1、option() : 设置服务端用于接收进来的连接,也就是bossGroup线程

2、childOption():是提供给父管道接收到的连接,也就是bossWork线程

SocketChannel参数,也就是childOption() 常用的参数:

SO_RCVBUF Socket参数,TCP数据接收缓冲区大小。

TCP_NODELAY TCP参数,立即发送数据,默认值为Ture。

SO_KEEPALIVE Socket参数,连接保活,默认值为False。启用该功能时,TCP会主动探测空闲连接的有效性。

ServerSocketChannel参数,也就是option()参数:即boss线程池的队列长度

SO_BACKLOG Socket参数,服务端接受连接的队列长度,如果队列已满,客户端连接将被拒绝。默认值,Windows为200,其他为128。

5.4.4、设置流水线(重点)

ChannelPipeline是Netty处理请求的责任链,ChannelHander则是具体处理请求的处理器。实际上每一个channel都有一个处理器的流水线。

好啦,今天的文章就到这里,希望能帮助到屏幕前迷茫的你们