netty 版本分为 netty3.x 和 netty4.x、netty5.x,因为 Netty5 出现重大 bug,已经被官网废弃了,目前推荐使用的是 Netty4.x 的稳定版本
在此之前,先介绍几个常用的数据请求的模式。 目前比较常见的模式有传统阻塞 I/O 服务模型,即一个请求一个线程,这个不再说。Reactor 模式:根据Reactor的数量又分为几种实现。
实现应用程序通过一个阻塞对象监听多路连接请求,Reactor 对象通过 Select 监控客户端请求事件,收到事件后通过 Dispatch 进行分发,如果是连接请求则由 Acceptor 通过 Accept 处理连接请求,如果不是,则由Handler 来响应
优点:模型简单,没有多线程、进程通信、竞争的问题,全部都在一个线程中完成 缺点:性能问题,只有一个线程,无法完全发挥多核 CPU 的性能,线程意外终止,或者进入死循环,会导致整个系统通信模块不可用,不能接收和处理外部消息,造成节点故障
前面跟上面单线程一样,也是select监控请求,然后收到请求,将其转发,如果是连接请求,则交给accept处理,如果不是,则交给handler处理,不同的是。这里handler只负责响应事件,不做具体的业务处理, 通过 read 读取数据后,会分发给后面的 worker 线程池的某个线程处理业务,worker 线程池会分配独立线程完成真正的业务,并将结果返回给 handler,然后通过 send 将结果返回给 client
这里充分发挥了CPU多线程的优势,也可以同时处理很多业务,但是 reactor需要 处理所有的事件的监听和响应,并且是单线程,这里在高并发会出现瓶颈。
跟上面不用的是,新增 MainReactor, MainReactor可以连接多个SubReactor,这就解决了一个Reactor性能瓶颈的问题。
Reactor 主线程 MainReactor 对象通过 select 监听连接事件, 收到事件后,通过 Acceptor 处理连接事件,当 Acceptor 处理连接事件后,MainReactor 将连接分配给 SubReactor,subreactor 将连接加入到连接队列进行监听,并创建 handler 进行各种事件处理当有新事件发生时, subreactor 就会调用对应的 handler 处理handler 通过 read 读取数据,分发给后面的 worker 线程处理worker 线程池分配独立的 worker 线程进行业务处理,并返回结果给client基本以上性能问题解决了,就是变成比较麻烦!
上面说了说了三种常用模式,Netty主要是基于主从 Reactors 多线程模型做了一定的改进。
简单来说就是BossGroup 负责请求接受,并将其注册到WorkerGroup ,然后WorkerGroup 中的select监听事件,有事件了就甩给下面的管道,管道里面有多线程可以同时处理很多业务,处理完返回就完事了、
下面的连接是一个用Netty写的案例,供参考:https://github.com/Coderxiangyang/NettyExercise/tree/master/NettySimple
Netty 中的 I/O 操作是异步的,包括 Bind、Write、Connect 等操作会简单的返回一个 ChannelFuture。调用者并不能立刻获得结果,而是通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得IO 操作结果, Netty 的异步模型是建立在 future 和 callback 的之上的。callback 就是回调。重点说 Future,它的核心思想是:假设一个方法 fun,计算过程可能非常耗时,等待 fun 返回显然不合适。那么可以在调用 fun 的时候,立马返回一个 Future,后续可以通过 Future 去监控方法 fun 的处理过程(即 : Future-Listener 机制)
当 Future 对象刚刚创建时,处于非完成状态,调用者可以通过返回的 ChannelFuture 来获取操作执行的状态, 注册监听函数来执行完成后的操作。 常见操作: 1、通过 isDone 方法来判断当前操作是否完成; 2、 通过 isSuccess 方法来判断已完成的当前操作是否成功; 3、 通过 getCause 方法来获取已完成的当前操作失败的原因; 4、 通过 isCancelled 方法来判断已完成的当前操作是否被取消; 5、 通过 addListener 方法来注册监听器,当操作已完成(isDone 方法返回完成),将会通知指定的监听器;如果 Future 对象已完成,则通知指定的监听器