zoukankan      html  css  js  c++  java
  • Netty入门

    前言:

    传统的 IO 模型中,一个线程对应一个连接,当有一个新连接时会创建一个新的线程,死循环接收数据。大多情况时,只有少量时间是有数据可读的,因此会造成资源浪费。

    在 NIO 模型中一个死循环检测多个连接是否有数据可读,这就是 selector,然后通过检查 selector 知道那些线程是有数据可读的,进而读取数据。

    Java 中 NIO 使用比较繁琐,因而使用已经被封装的使用起来非常方便的框架—— Netty 。

    传统IO 和 NIO 处理多个连接的图示:

    使用阻塞 I/O 处理多个连接
    【使用阻塞 I/O 处理多个连接】

    使用 Selector 的非阻塞 I/O
    【使用 Selector 的非阻塞 I/O】

    1. Netty 是什么

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

    异步:异步非阻塞 I/O

    事件驱动:当有事件触发时,才会调用处理器进行数据处理

    网络应用框架:网络编程的支持

    2. Netty 中的 Reactor 线程模型

    前言中提到了传统阻塞的I/O 线程,Netty 中开多个线程,每个线程管理着一批连接。

    Reactor 线程模型可分为单线程版 多线程版和主从模型版

    2.1 单线程模型

    单线程版: 一个Reactor线程负责连接,负责分发请求,顺序处理每个连接的业务逻辑。虽然一次可以处理多个请求,但实现上还是一个线程完成所有的任务。不适合多核CPU。

    代码实现方式:

    private EventLoopGroup group = new NioEventLoopGroup();
    ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(group)
                    .childHandler(new HeartbeatInitializer());
    

    2.2 多线程模型

    多线程版: 相比上一种模式,该模型在分配处理部分采用了多线程(线程池),可以解决 CPU 密集型的业务逻辑。但是在Acceptor连接线程上还是单个,如果服务是高I/O 的话还是不能满足需求,也没办法利用多核。

    代码实现方式:

    private EventLoopGroup boss = new NioEventLoopGroup(1);
    private EventLoopGroup work = new NioEventLoopGroup();
    ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(boss,work)
                    .childHandler(new HeartbeatInitializer());
    

    2.3 主从模型版

    主从模型:该模型相比第二种模型,是将Reactor分成两部分,mainReactor负责监听server socket,accept新连接;并将建立的socket分派给subReactor。subReactor负责多路分离已连接的socket,读写网络数据,对业务处理功能,其扔给worker线程池完成。通常,subReactor个数上可与CPU个数等同或为核数的两倍。

    2.4 Netty 主从多线程模型

    Netty 监听客户端连接是一个线程组管理的,而监听客户端读写的任务是由另一个线程组来管理的。Netty 的线程模型是 Reactor 模型的变种,那就是去掉线程池的第三种形式的变种,这也是 Netty NIO的默认模式。

    netty线程模型

    代码实现:

    private EventLoopGroup boss = new NioEventLoopGroup();
    private EventLoopGroup work = new NioEventLoopGroup();
    ServerBootstrap bootstrap = new ServerBootstrap()
                    .group(boss,work)
                    .childHandler(new HeartbeatInitializer());
    

    在处理时也可加线程池进行处理,使其成为第三种模型。

    3. Netty 基本概念

    客户端和服务端连接图示:

    3.1 NioEventLoop

    服务端监听的端口,传统的 Server Socket。

    开启两种线程,一种监听客户端连接,一种处理客户端读写。

    3.2 Channel

    客户端和服务端连接的封装,可以理解为Socket

    在Channel连接的封装上面可以进行读写。

    3.3 ChannelHandler

    Pipeline 中的 ChannelHandler

    对数据进行业务处理的逻辑。在逻辑处理链Pipeline上的逻辑处理。

    3.4 Decoder 和 Encoder

    编码和解码,基于TCP 通信的数据包是基于二进制的。客户端需要将一个Java对象按照通信协议编码为一个二进制数据包,服务端接受后需要进行拆包 将二进制数据包解码为Java对象,交给业务处理。处理后按照同样的通信协议进行编码给客户端返回。

    3.5 ByteBuf

    ByteBuf 是 Netty 对二进制数据抽象的数据结构,可以更方便的操作二进制数据。

    3.6 Pipeline

    Channel 上面逻辑处理链

  • 相关阅读:
    javascript学习_函数调用模式与this取值
    Git 学习笔记(Git教程-廖雪峰)
    Linux学习一周初体验
    前言_写在立冬时
    2021.10.24驾考日记
    大二上学期的HTML杂碎
    AISing Programming Contest 2021(AtCoder Beginner Contest 202)D题题解
    并查集两优化——按秩合并与路径压缩
    [算法板子] 求拓扑序列(拓扑排序)
    浅谈迭代加深搜索 ( IDDFS )
  • 原文地址:https://www.cnblogs.com/wei57960/p/12548525.html
Copyright © 2011-2022 走看看