其他分享
首页 > 其他分享> > Netty

Netty

作者:互联网

学习本章需要先知道IO多路复用,不清楚的请移步:IO多路复用

网络通信中,阻塞IO两大阻塞的地方:socket链接阻塞,等待读取文件阻塞。 本地文件io就只有一个等待文件阻塞

一.Reactor模型(Netty线程模型)

说Netty之前先说一下高性能网络模式Reactor。由于NIO是面向过程编写,效率太低。大佬们基于面向对象的思想,对 I/O 多路复用作了一层封装,让使用者不用考虑底层网络 API 的细节,只需要关注应用代码的编写。大佬们还为这种模式取了个让人第一时间难以理解的名字:Reactor 模式。意思对事件的反应,来了一个事件(连接请求,读写请求),Reactor 就有相对应的反应/响应。

Reactor有3种经典方案:


 单Reactor单线程:

  1. Reactor 对象通过 select (IO 多路复用接口) 监听事件,收到事件后通过 dispatch 进行分发,具体分发给 Acceptor 对象还是 Handler 对象,还要看收到的事件类型;
  2. 如果是连接建立的事件,则交由 Acceptor 对象进行处理,Acceptor 对象会通过 accept 方法 获取连接,并创建一个 Handler 对象来处理后续的响应事件;
  3. 如果不是连接建立事件, 则交由当前连接对应的 Handler 对象来进行响应;
  4. Handler 对象通过 read -> 业务处理 -> send 的流程来完成完整的业务流程。

 缺点:

适用场景:单 Reactor 单进程的方案不适用计算机密集型的场景,只适用于业务处理非常快速的场景。


 单Reactor多线程:

前面的三个步骤和单 Reactor 单线程方案是一样的,我们只看不一样的部分:

  1. Handler 对象不再负责业务处理,只负责数据的接收和发送,Handler 对象通过 read 读取到数据后,会将数据发给线程池中的线程进行业务处理;
  2. 处理完后,将结果发给主线程中的 Handler 对象,接着由 Handler 通过 send 方法将响应结果发送给 client;

 缺点:


多Reactor多线程(主从Reactor多线程):

和单Reactor多线程唯一不同的是,将连接请求和读写请求分别发给不同的Reactor进行处理。该模式应用于Netty,Memcache等项目中


 那么我们看看Netty到底是什么样的模型:

具体细节下面详细说明!

二.Netty概述

 Netty 是什么?


为什么要用 Netty?因为 Netty 具有下面这些优点,并且相比于直接使用 JDK 自带的 NIO 相关的 API 来说更加易用。


Netty 应用场景了解么?理论上来说,NIO 可以做的事情 ,使用 Netty 都可以做并且更好。Netty 主要用来做网络通信 :

三.Netty 核心组件有哪些?分别有什么作用?

Bootstrap,ServerBootstrap

引导,一个Netty通常又一个Bootstrap开始,主要作用是配置整个Netty程序,串联各个组件。

Bootstrap 是客户端的启动引导类/辅助类,具体使用方法如下:

 EventLoopGroup group = new NioEventLoopGroup();
        try {
            //创建客户端启动引导/辅助类:Bootstrap
            Bootstrap b = new Bootstrap();
            //指定线程模型
            b.group(group).
                    ......
            // 尝试建立连接
            ChannelFuture f = b.connect(host, port).sync();
            f.channel().closeFuture().sync();
        } finally {
            // 优雅关闭相关线程组资源
            group.shutdownGracefully();

ServerBootstrap 客户端的启动引导类/辅助类,具体使用方法如下:

 // 1.bossGroup 用于接收连接,workerGroup 用于具体的处理
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //2.创建服务端启动引导/辅助类:ServerBootstrap
            ServerBootstrap b = new ServerBootstrap();
            //3.给引导类配置两大线程组,确定了线程模型
            b.group(bossGroup, workerGroup).
                   ......
            // 6.绑定端口
            ChannelFuture f = b.bind(port).sync();
            // 等待连接关闭
            f.channel().closeFuture().sync();
        } finally {
            //7.优雅关闭相关线程组资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }

说明:


Channel:(在代码层面,读写,连接操作看似交给BootStrap,其实是交给Channel)

Channel 接口是 Netty 对网络操作抽象类,它除了包括基本的 I/O 操作,如 bind()connect()read()write() 等。

比较常用的Channel接口实现类是NioServerSocketChannel(服务端)和NioSocketChannel(客户端),这两个 Channel 可以和 BIO 编程模型中的ServerSocket以及Socket两个概念对应上。


ChannelFuture

Netty 是异步非阻塞的,所有的 I/O 操作都为异步的。因此,我们不能立刻得到操作是否执行成功,但是,可通过下面2种方式知道:


EventLoop 与 EventLoopGroup:


Selector和TaskQueue


 ChannelPipeline和ChannelHandler :

四.Netty服务端和客户端的启动过程了解么?
    // 1.bossGroup 用于接收连接,workerGroup 用于具体的处理
        EventLoopGroup bossGroup = new NioEventLoopGroup(1);
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            //2.创建服务端启动引导/辅助类:ServerBootstrap
            ServerBootstrap b = new ServerBootstrap();
            //3.给引导类配置两大线程组,确定了线程模型
            b.group(bossGroup, workerGroup)
                    // (非必备)打印日志
                    .handler(new LoggingHandler(LogLevel.INFO))
                    // 4.指定 IO 模型
                    .channel(NioServerSocketChannel.class)
                    .childHandler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        public void initChannel(SocketChannel ch) {
                            ChannelPipeline p = ch.pipeline();
                            //5.可以自定义客户端消息的业务处理逻辑
                            p.addLast(new HelloServerHandler());
                        }
                    });
            // 6.绑定端口,调用 sync 方法阻塞直到绑定完成
            ChannelFuture f = b.bind(port).sync();
            // 7.阻塞等待直到服务器Channel关闭(closeFuture()方法获取Channel 的CloseFuture对象,然后调用sync()方法)
            f.channel().closeFuture().sync();
        } finally {
            //8.优雅关闭相关线程组资源
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
 五.其他小问题

 Netty 长连接?


Netty心跳机制了解么?


Netty 的零拷贝了解么?

在 OS 层面上的 Zero-copy 通常指避免在 用户态(User-space) 与 内核态(Kernel-space) 之间来回拷贝数据。而在 Netty 层面 ,零拷贝主要体现在对于数据操作的优化。


NioEventLoopGroup 默认的构造函数会起多少线程?

 

寄语:当努力到一定程度,幸运自会与你不期而遇

标签:Netty,Reactor,线程,new,连接,Channel
来源: https://www.cnblogs.com/monkey-xuan/p/15878652.html