【博学谷学习记录】超强总结,用心分享|狂野架构师Netty

Netty核心架构

核心:

可扩展的事件模型

统一的通信api,简化了通信编码

零拷贝机制与丰富的字节缓冲区

传输服务:

支持socket以及datagram(数据报)

http传输服务

In-VM Pipe (管道协议,是jvm的一种进程)

协议支持:

http 以及 websocket

SSL 安全套接字协议支持

Google Protobuf (序列化框架)

支持zlib、gzip压缩

支持大文件的传输

RTSP(实时流传输协议,是TCP/IP协议体系中的一个应用层协议)

支持二进制协议并且提供了完整的单元测试

选Netty的理由

API

Netty更友好更强大

1、JDK中NIO的一些API功能薄弱且复杂,Netty隔离了JDK中NIO的实现变化及实现细节

譬如:ByteBuffer -> ByteBuf主要负责从底层的IO中读取数据到ByteBuf,然后传递给应用程序,应用程序处理完之后封装为ByteBuf,写回给IO

并发编程

Netty自身线程安全使用JDK原生API需要对多线程要 很 熟 悉 , 因 为 N I O 涉 及 到Reactor设计模式,得对里面的原理要相当的熟悉

高可用

JDK原生方式要实现高可用,需要自己实现断路重连、半包读写、粘包处理、失败缓存处理等相关操作,而Netty则做的更多,它解决了传输的一些问题譬如粘包半包现象,它支持常用的应用层协议,完善的断路重连,idle等异常处理

Bug

JDK的NIO存在bug,如经典的epoll bug,会导致CPU 100%而Netty封装的更完善。

Netty中的Reactor实现

Netty线程模型是基于Reactor模型实现的,对Reactor三种模式都有非常好的支持,并做了一定的改进,也非

常的灵活,一般情况,在服务端会采用主从架构模型

工作流程

1.Netty 抽象出两组线程池:BossGroup 和 WorkerGroup,每个线程池中都有EventLoop 线程(可以是OIO,NIO,AIO)。BossGroup中的线程专门负责和客户端建立连接,WorkerGroup 中的线程专门负责处理连接上的读写, EventLoopGroup 相当于一个事件循环组, 这个组中含有多个事件循环

2.EventLoop 表示一个不断循环的执行事件处理的线程,每个EventLoop 都包含一个 Selector,用于监听注册在其上的 Socket 网络连接(Channel)。

3.每个 Boss EventLoop 中循环执行以下三个步骤:

3.1select:轮训注册在其上的 ServerSocketChannel 的 accept 事件(OP_ACCEPT 事件)

3.2processSelectedKeys:处理 accept 事件,与客户端建立连接,生成一个SocketChannel,并将其注册到某个 Worker EventLoop 上的 Selector 上

3.3runAllTasks:再去以此循环处理任务队列中的其他任务

4.每个 Worker EventLoop 中循环执行以下三个步骤:

4.1select:轮训注册在其上的SocketChannel 的 read/write 事件(OP_READ/OP_WRITE 事件)

4.2processSelectedKeys:在对应的SocketChannel 上处理 read/write 事件

4.3runAllTasks:再去以此循环处理任务队列中的其他任务

5.在以上两个processSelectedKeys步骤中,会使用 Pipeline(管道),Pipeline 中引用了 Channel,即通过 Pipeline 可以获取到对应的 Channel,Pipeline 中维护了很多的处理器(拦截处理器、过滤处理器、自定义处理器等)。

Netty 线程模型其他事项

1.Netty 的线程模型基于主从多Reactor模型。通常由一个线程负责处理OP_ACCEPT事件,拥有 CPU 核数的两倍的IO线程处理读写事件

2.一个通道的IO操作会绑定在一个IO线程中,而一个IO线程可以注册多个通道

3.在一个网络通信中通常会包含网络数据读写,编码、解码、业务处理。默认情况下网络数据读写,编码、解码等操作会在IO线程中运行,但也可以指定其他线程池。

4.通常业务处理会单独开启业务线程池(看业务类型),但也可以进一步细化,例如心跳包可以直接在IO线程中处理,而需要再转发给业务线程池,避免线程切换

5.在一个IO线程中所有通道的事件是串行处理的。

6.通常业务操作会专门开辟一个线程池,那业务处理完成之后,如何将响应结果通过 IO 线程写入到网卡中呢?业务线程调用 Channel对象的 write 方法并不会立即写入网络,只是将数据放入一个待写入缓存区,然后IO线程每次执行事件选择后,会从待写入缓存区中获取 写入任务,将数据真正写入到网络中

posted @ 2022-08-21 23:30  谢十二♡Lgy  阅读(41)  评论(0编辑  收藏  举报