1.什么是Netty
Netty是一个基于Java NIO的网络编程框架,提供了简单而强大的API,用于快速开发可扩展的网络应用程序。其核心思想是异步、事件驱动的网络通信模型,通过事件处理器链(ChannelHandler)实现高效的数据处理和传输。
2. Netty与工业物联网之间的联系
工业物联网 (IIoT) 是指将传感器、设备和工厂系统连接到互联网,以实现实时监控、数据分析和远程控制等目的的技术。Netty 在工业物联网中有着重要的作用,具体体现在以下几个方面:
(1) 高性能的网络通信:工业物联网通常需要处理大量的数据流量和高并发的连接。Netty 提供了基于事件驱动的异步 IO 模型,能够高效地处理大规模的网络通信,确保系统具有优异的性能和可伸缩性。
(2) 协议支持:工业物联网中常用的通信协议有 MQTT、CoAP、AMQP 等,而 Netty 提供了灵活的网络编程接口和丰富的协议支持,可以轻松地实现对这些协议的解析和处理,从而实现设备之间的可靠通信。
(3) 实时数据处理:工业物联网需要及时处理从各种传感器和设备收集到的数据,进行实时监控、分析和控制。Netty 的高性能和低延迟特性使得它非常适合用于处理实时数据流,能够快速响应设备的数据上传和控制指令。
(4) 安全性和稳定性:工业物联网系统对安全性和稳定性要求极高,Netty 提供了丰富的安全功能和可靠的错误处理机制,能够保障系统的数据传输安全和稳定运行。
综上所述,Netty 在工业物联网领域的应用非常广泛,它为工业物联网系统的开发和部署提供了强大的网络通信基础支持。
3. Netty核心组件
(1) Bootstrap
用于启动和配置网络应用程序配置类。通过Bootstrap可以绑定启动IP、端口,配置EventLoopGroup、选择传输协议(Channel)、配置ChannelHandler、参数调优设置等。Bootstrap通常与ServerBootstrap配合使用。ServerBootstrap用于服务端,Bootstrap用于客户端。
(2) EventLoop
Netty为了避免线程与线程之间产生并发冲突,采用的策略。负责处理所有的I/O事件,如接收连接、读取数据、写入数据等。EventLoop在一个线程中循环执行,通过事件驱动的方式处理事件。一个EventLoop可以关联一个或多个Channel,但一个Channel只能关联一个EventLoop。EventLoop通常在服务端需要实例化2个对象,一个用于接受处理客户端的连接请求,另一个用户处理I/O读写事件。它的继承关系比较复杂,一条线是继承自 j.u.c.ScheduledExecutorService 因此包含了线程池中所有的方法,另一条线是继承自 netty 自己的 OrderedEventExecutor。
(3) Channel
一个与实际数据传输相关的连接。可以理解为数据在客户端和服务器之间的通道。Channel提供了异步的I/O操作,如读取、写入和关闭等。打个比喻,每个 Channel 是一个产品的加工车间,Pipeline 是车间中的流水线,ChannelHandler 就是流水线上的各道工序,而后面要讲的 ByteBuf 是原材料,经过很多工序的加工:先经过一道道入站工序,再经过一道道出站工序最终变成产品
(4) ChannelHandler
最核心的组件之一,负责处理输入输出数据的逻辑。可以接收入站事件(如数据接收)和出站事件(如数据发送),并执行相应的处理逻辑。ChannelHandler被添加到ChannelPipeline中,形成处理链。
(5) ChannelPipline
ChannelPipeline是一个双向链表,拦截和处理事件的链式结构。ChannelPipeline中的ChannelHandler是一个传播链,ChannelPipeline管理ChannelHandler并协调它们的处理顺序。当数据通过Channel时,它会依次经过每个ChannelHandler进行处理。
(6) ByteBuf
数据传输的基本单元,用于处理二进制数据的数据结构。ByteBuf提供了灵活的API,可以高效地读取、写入和操作数据。
ByteBuf的优势:
1.池化 - 可以重用池中 ByteBuf 实例,更节约内存,减少内存溢出的可能
2.可以自动扩容
3.支持链式调用,使用更流畅
4.很多地方体现零拷贝,例如 slice、duplicate、CompositeByteBuf
4. Netty入门
开发一个简单的服务器端和客户端
4.1 服务器端
(1) 1 处,创建 NioEventLoopGroup,可以简单理解为 线程池 + Selector
(2) 2 处,选择服务 Scoket 实现类,其中 NioServerSocketChannel 表示基于 NIO 的服务器端实现
(3) 3 处,为啥方法叫 childHandler,是接下来添加的处理器都是给 SocketChannel 用的,而不是给 ServerSocketChannel。ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器
(4) 4 处,ServerSocketChannel 绑定的监听端口
(5) 5 处,SocketChannel 的处理器,解码 ByteBuf => String
(6) 6 处,SocketChannel 的业务处理器,使用上一个处理器的处理结果
4.2 客户端
(1) 1 处,创建 NioEventLoopGroup,同 Server
(2) 2 处,选择客户 Socket 实现类,NioSocketChannel 表示基于 NIO 的客户端实现
(3) 3 处,添加 SocketChannel 的处理器,ChannelInitializer 处理器(仅执行一次),它的作用是待客户端 SocketChannel 建立连接后,执行 initChannel 以便添加更多的处理器
(4) 4 处,指定要连接的服务器和端口
(5) 5 处,Netty 中很多方法都是异步的,如 connect,这时需要使用 sync 方法等待 connect 建立连接完毕
(6) 6 处,获取 channel 对象,它即为通道抽象,可以进行数据读写操作
(7) 7 处,写入消息并清空缓冲区
(8) 8 处,消息会经过通道 handler 处理,这里是将 String => ByteBuf 发出
数据经过网络传输,到达服务器端,服务器端 5 和 6 处的 handler 先后被触发,走完一个流程
4.3 流程梳理