Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。
基本介绍
Netty是一个高性能、异步事件驱动的NIO框架,它提供了对TCP、UDP和文件传输的支持,作为一个异步NIO框架,Netty的所有IO操作都是异步非阻塞的,通过Future-Listener机制,用户可以方便的主动获取或者通过通知机制获得IO操作结果。
作为当前最流行的NIO框架,Netty在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,一些业界著名的开源组件也基于Netty的NIO框架构建。
GitHub:https://github.com/netty/netty
官网:https://netty.io/
「Netty的优缺点」
之前我们使用JAVA NIO的时候会有一些问题:
JDK NIO的BUG,例如臭名昭著的epoll bug,它会导致Selector空轮询,最终导致CPU 100%,官方声称在JDK 1.6版本的update18修复了该问题,但是直到JDK 1.7版本该问题仍旧存在,只不过该BUG发生概率降低了一些而已,它并没有得到根本性解决。
客户端面临断连重连、网络闪断、半包读写、失败缓存、网络拥塞和异常码流的处理等问题需要处理。
Netty的优点:
API使用简单,开发门槛低;
功能强大,预置了多种编解码功能,支持多种主流协议;
定制能力强,可以通过ChannelHandler对通信框架进行灵活地扩展;
性能高,通过与其他业界主流的NIO框架对比,Netty的综合性能最优;
成熟、稳定,Netty修复了已经发现的所有JDK NIO BUG,业务开发人员不需要再为NIO的BUG而烦恼;
社区活跃,版本迭代周期短,发现的BUG可以被及时修复,同时,更多的新功能会加入;
经历了大规模的商业应用考验,质量得到验证。
Netty有一个最重要的缺点:大版本不兼容,3.x/4.x同时维护,5.x放弃维护,主要原因是Netty抛弃了Jboss单独发展了。
「Netty的应用产品」
Netty 经过很多出名产品在线上的大规模验证,其健壮性和稳定性都被业界认可,其中典型的产品有一下几个
服务治理:Apache Dubbo、GRPC。
大数据:Hbase、Spark、Flink、Storm。
搜索引擎:Elasticsearch。
消息队列:RocketMQ、ActiveMQ。
Spring WebFlux是伴随Spring framework 5提出的网络框架解决方案,也是基于Netty实现。
还有更多优秀的产品可以参考下面网址:https://netty.io/wiki/related-projects.html。
入门案例
构建一个简单的应用程序:客户端将消息发送给服务器,而服务器再将消息会送给客户端。
首先,引入 Maven 依赖
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId>
/dependency>
「服务端:」
Netty 服务器都需要以下两部分:
至少一个ChannelHandler,该组件实现了服务器对从客户端接收的数据的处理,即它的业务逻辑。
配置引导服务器的启动代码,它会将服务器绑定到它要监听连接请求的端口上。
「ChannelHandler服务端业务逻辑」
因为你的 Echo 服务器会响应传入的消息,所以它需要实现 ChannelInboundHandler 接口,用来定义响应入站事件的方法。
这个简单的应用程序只需要用到少量的这些方法,所以继承 ChannelInboundHandlerAdapter 类也就足够了,它提供了 ChannelInboundHandler 的默认实现。
我们需要的方法是:
channelRead(),对于每个传入的消息都要调用;
channelReadComplete(),通知ChannelInboundHandler最后一次对channelRead()的调用是当前批量读取中的最后一条消息;
exceptionCaught(),在读取操作期间,有异常抛出时会调用。
该 Echo 服务器的 ChannelHandler 实现是 EchoServerHandler:
「引导服务器」
引导过程中所需要的步骤如下:
创建一个 ServerBootstrap 的实例以引导和绑定服务器;
创建并分配一个 NioEventLoopGroup 实例以进行事件的处理,如接受新连接以及读/写数据;
指定服务器绑定的本地的 InetSocketAddress;
使用一个 EchoServerHandler 的实例初始化每一个新的 Channel;
调用 ServerBootstrap.bind()方法以绑定服务器。
「客户端:」
Echo 客户端将会:
连接到服务器;
发送一个或者多个消息;
对于每个消息,等待并接收从服务器发回的相同的消息;
关闭连接。
编写客户端所涉及的两个主要代码部分也是业务逻辑和引导
「ChannelHandler实现客户端逻辑」
如同服务器,客户端将拥有一个用来处理数据的 ChannelInboundHandler。
在这 个场景下,你将扩展 SimpleChannelInboundHandler 类以处理所有必须的任务。
这要求重写下面的方法:
channelActive()——在到服务器的连接已经建立之后将被调用;
channelRead0()——当从服务器接收到一条消息时被调用;
exceptionCaught()——在处理过程中引发异常时被调用。
「引导客户端」
为初始化客户端,创建了一个 Bootstrap 实例;
为进行事件处理分配了一个 NioEventLoopGroup 实例,其中事件处理包括创建新的连接以及处理入站和出站数据;
为服务器连接创建了一个 InetSocketAddress 实例;
当连接被建立时,一个 EchoClientHandler 实例会被安装到ChannelPipeline 中;
在一切都设置完成后,调用 Bootstrap.connect()方法连接到远程节点;
基本架构
Netty 的逻辑处理架构为典型网络分层架构设计,共分为网络通信层、事件调度层、服务编排层,每一层各司其职。
分层讲解:https://www.51cto.com/article/683699.html