Java充电社
专辑
博文
联系我
本人继续续收门徒,亲手指导
Netty第5篇:总结
相关专辑:
Netty专题
<div style="display:none"></div> ## 简介 Netty 是由 JBOSS 提供的一个 java 开源框架。 Netty 提供异步的、事件驱动的网络应用程序框架和工具,用以快速开发高性能、高可靠性的网络服务器和客户端程序。 Netty 是一个基于 NIO 的客户、服务器端编程框架,使用 Netty 可以确保你快速和简单的开发出一个网络应用,例如实现了某种协议的客户、服务端应用。 Netty 是一个吸收了多种协议(包括 FTP、 SMTP、 HTTP等各种二进制文本协议)的实现经验,并经过相当精心设计的项目。 Netty 在互联网领域、大数据分布式计算领域、游戏行业、通信行业等获得了广泛的应用,Elasticsearch和Dubbo就是基于netty设计的。 ## Reactor模型 ### Reactor单线程模型 用户发起 IO 请求到 Reactor 线程,Ractor 线程将用户的 IO 请求放入到通道,然后再进行后续处理,处理完成后,Reactor 线程重新获得控制权,继续其他客户端的处理。 这种模型一个时间点只有一个任务在执行,这个任务执行完了,再去执行下一个任务。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/404/6f398cb6-9c4a-4a9a-a489-508d88e105e7.png) ### Reactor多线程模型 Reactor 多线程模型是由一组 NIO 线程来处理 IO 操作(之前是单个线程),所以在请求处理上会比上一中模型效率更高,可以处理更多的客户端请求。 这种模式使用多个线程执行多个任务, 任务可以同时执行。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/404/58f7caf7-7b88-4b86-9fc2-a8ba469f8bc8.png) ### Reactor主从多线程模型 这种线程模型是 Netty 推荐使用的线程模型。这种模型适用于高并发场景,一组线程池接收请求,一组线程池处理 IO。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/404/758dfe3d-2ed4-4277-87ca-16464a225d1e.png) ## Netty模型 ### 线程模型 Server端包含1个Boss NioEventLoopGroup和1个Worker NioEventLoopGroup。NioEventLoopGroup相当于1个事件循环组,这个组里包含多个事件循环NioEventLoop,每个NioEventLoop包含1个selector和1个事件循环线程。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/404/58da262f-69bb-4d3d-823c-620c095991d2.png) ### Boss、Worker、NioEventLoop BossGroup专门负责接收客户端连接,WorkerGroup专门负责网络读写操作。NioEventLoop表示一个不断循环执行处理任务的线程,每个 NioEventLoop 都有一个 selector,用于监听绑定在其上的 socket 网络通道。NioEventLoop内部采用串行化设计,从消息的读取->解码->处理->编码->发送,始终由 IO 线程 NioEventLoop 负责。 对应关系: 一个 NioEventLoopGroup 下包含多个 NioEventLoop 每个 NioEventLoop 中包含有一个 Selector,一个 taskQueue 每个 NioEventLoop 的 Selector 上可以注册监听多个 NioChannel 每个 NioChannel 只会绑定在唯一的 NioEventLoop 上 每个 NioChannel 都绑定有一个自己的 ChannelPipeline ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/404/0470ae87-e44f-4c37-a5b2-576641a27d33.jpg) ### 每个Boss NioEventLoop循环执行的任务包含3步 1 轮询accept事件 2 处理accept I/O事件,与Client建立连接,生成NioSocketChannel,并将NioSocketChannel注册到某个Worker NioEventLoop的Selector上 3 处理任务队列中的任务,runAllTasks。任务队列中的任务包括用户调用eventloop.execute或schedule执行的任务,或者其它线程提交到该eventloop的任务。 ### 每个Worker NioEventLoop循环执行的任务包含3步 1 轮询read、write事件; 2 处I/O事件,即read、write事件,在NioSocketChannel可读、可写事件发生时进行处理 3 处理任务队列中的任务,runAllTasks。 ### 异步模型 异步的概念和同步相对。当一个异步过程调用发出后,调用者不能立刻得到结果。实际处理这个调用的组件在完成后,通过状态、 通知和回调来通知调用者。 ### Future,Callback和Handler Netty 的异步模型是建立在 future 和 callback 的之上的,callback 就是回调。Future表示异步的执行结果, 可以通过它提供的方法来检测执行是否完成。 在使用 Netty 进行编程时,拦截操作和转换出入站数据只需要您提供 callback 或利用future 即可。 ### Future-Listener机制 Future的核心思想是:假设一个方法 fun,计算过程可能非常耗时,等待 fun 返回显然不合适。那么可以在调用 fun 的时候,立马返回一个 Future, 后续可以通过 Future 去监控方法 fun 的处理过程。 Netty 中的 I/O 操作是异步的,包括 Bind、 Write、 Connect 等操作会简单的返回一个 ChannelFuture。调用者并不能立刻获得结果,而是通过 Future-Listener 机制,用户可以方便的主动获取或者通过通知机制获得IO 操作结果。 链式操作 在使用 Netty 进行编程时, 拦截操作和转换出入站数据等使用链式操作,只需要提供 callback 或利用future 即可实现,Handler由于事件的处理。 ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/404/c83306cb-7ce3-43ad-a579-b7dd48d7fe0d.jpg) ## Netty中的主要类 ### ChannelHandle 我们经常需要自定义一个Handler类去继承 ChannelInboundHandlerAdapter,然后通过重写相应方法实现业务逻辑,一般需要重写的方法: 常用方法: ```java public void channelActive(ChannelHandlerContext ctx) 通道就绪事件 public void channelRead(ChannelHandlerContext ctx, Object msg) 通道读取数据事件 public void channelReadComplete(ChannelHandlerContext ctx) 数据读取完毕事件 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) 通道发生异常事件 ``` ### Pipeline 和 ChannelPipeline ChannelPipeline是一个Handler的集合,它负责处理和拦截 inbound 或者 outbound 的事件和操作,相当于一个贯穿 Netty 的链。 常用方法: ```java ChannelPipeline addFirst(ChannelHandler... handlers) 把一个业务处理类(handler)添加到链中的第一个位置 ChannelPipeline addLast(ChannelHandler... handlers) 把一个业务处理类(handler)添加到链中的最后一个位置 ``` ### ChannelHandlerContext 这是事件处理器上下文对象,Pipeline链中的实际处理节点 。 每个处理节点ChannelHandlerContext 中包含一个具体的事件处理器 ChannelHandler, 同时ChannelHandlerContext 中也绑定了对应的 pipeline 和 Channel 的信息,方便对 ChannelHandler进行调用。 常用方法: ```java ChannelFuture close() 关闭通道 ChannelOutboundInvoker flush() 刷新 ChannelFuture writeAndFlush(Object msg) 将数据写到ChannelPipeline中当前ChannelHandler的下一个ChannelHandler开始处理。 ``` ### ChannelOption Netty 在创建 Channel 实例后,一般都需要设置 ChannelOption 参数。ChannelOption 是 Socket 的标准参数,而非 Netty 独创的。 常用的参数配置有两个: ```text ChannelOption.SO_BACKLOG ``` 对应 TCP/IP 协议 listen 函数中的 backlog 参数,用来初始化服务器可连接队列大小。 服务端处理客户端连接请求是顺序处理的,所以同一时间只能处理一个客户端连接。 多个客户端来的时候,服务端将不能处理的客户端连接请求放在队列中等待处理,backlog 参数指定了队列的大小。 ```java ChannelOption.SO_KEEPALIVE ``` 一直保持连接活动状态。 ### ChannelFuture 表示 Channel 中异步 I/O 操作的结果,在 Netty 中所有的 I/O 操作都是异步的,I/O 的调用会直接返回,调用者并不能立刻获得结果,但是可以通过 ChannelFuture 来获取 I/O 操作的处理状态。 常用方法: ```java Channel channel() 返回当前正在进行 IO 操作的通道 ChannelFuture sync() 等待异步操作执行完毕 ``` ### EventLoopGroup和其实现类 NioEventLoopGroup EventLoopGroup 是一组 EventLoop 的抽象,Netty 为了更好的利用多核 CPU 资源,一般会有多个 EventLoop 同时工作,每个 EventLoop 维护着一个 Selector 实例。 EventLoopGroup 提供 next 接口,可以从组里面按照一定规则获取其中一个 EventLoop来处理任务。 在 Netty 服务器端编程中,我们一般都需要提供两个 EventLoopGroup,例如:BossEventLoopGroup 和 WorkerEventLoopGroup。 通常一个服务端口即一个 ServerSocketChannel对应一个Selector 和一个EventLoop线程。BossEventLoop 负责接收客户端的连接并将 SocketChannel 交给 WorkerEventLoopGroup 来进行 IO 处理。 BossEventLoopGroup和WorkerEventLoopGroup执行流程: BossEventLoopGroup 通常是一个单线程的 EventLoop,EventLoop 维护着一个注册了ServerSocketChannel 的 Selector 实例, BossEventLoop 不断轮询 Selector 将连接事件分离出来,通常是 OP_ACCEPT 事件,然后将接收到的 SocketChannel 交给 WorkerEventLoopGroup, WorkerEventLoopGroup 会由 next 选择其中一个 EventLoopGroup 来将这个 SocketChannel 注册到其维护的 Selector 并对其后续的 IO 事件进行处理。 常用方法: ```java public NioEventLoopGroup() 构造方法 public Future<?> shutdownGracefully() 断开连接,关闭线程 ``` ### ServerBootstrap 和 Bootstrap ServerBootstrap 是 Netty 中的服务器端启动助手,通过它可以完成服务器端的各种配置; Bootstrap 是 Netty 中的客户端启动助手,通过它可以完成客户端的各种配置。 常用方法: ```java public ServerBootstrap group(EventLoopGroup parentGroup, EventLoopGroup childGroup) 该方法用于服务器端,用来设置两个 EventLoop public B group(EventLoopGroup group) 该方法用于客户端,用来设置一个 EventLoop public B channel(Class<? extends C> channelClass) 该方法用来设置一个服务器端的通道实现 public <T> B option(ChannelOption<T> option, T value) 用来给 ServerChannel 添加配置 public <T> ServerBootstrap childOption(ChannelOption<T> childOption, T value) 用来给接收到的通道添加配置 public ServerBootstrap childHandler(ChannelHandler childHandler) 该方法用来设置业务处理类(自定义的 handler) public ChannelFuture bind(int inetPort) 该方法用于服务器端,用来设置占用的端口号 public ChannelFuture connect(String inetHost, int inetPort) 该方法用于客户端,用来连接服务器端 ``` ### Unpooled 类 Unpooled 是 Netty 提供的一个专门用来操作缓冲区的工具类。 常用方法: ```java public static ByteBuf copiedBuffer(CharSequence string, Charset charset) 通过给定的数据和字符编码返回一个 ByteBuf 对象( 类似于 NIO 中的 ByteBuffer 对象) ``` <a style="display:none" target="_blank" href="https://mp.weixin.qq.com/s/_S1DD2JADnXvpexxaBwLLg" style="color:red; font-size:20px; font-weight:bold">继续收门徒,亲手带,月薪 4W 以下的可以来找我</a> ## 最新资料 1. <a href="https://mp.weixin.qq.com/s?__biz=MzkzOTI3Nzc0Mg==&mid=2247484964&idx=2&sn=c81bce2f26015ee0f9632ddc6c67df03&scene=21#wechat_redirect" target="_blank">尚硅谷 Java 学科全套教程(总 207.77GB)</a> 2. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484192&idx=1&sn=505f2faaa4cc911f553850667749bcbb&scene=21#wechat_redirect" target="_blank">2021 最新版 Java 微服务学习线路图 + 视频</a> 3. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484573&idx=1&sn=7f3d83892186c16c57bc0b99f03f1ffd&scene=21#wechat_redirect" target="_blank">阿里技术大佬整理的《Spring 学习笔记.pdf》</a> 4. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247484544&idx=2&sn=c1dfe907cfaa5b9ae8e66fc247ccbe84&scene=21#wechat_redirect" target="_blank">阿里大佬的《MySQL 学习笔记高清.pdf》</a> 5. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485167&idx=1&sn=48d75c8e93e748235a3547f34921dfb7&scene=21#wechat_redirect" target="_blank">2021 版 java 高并发常见面试题汇总.pdf</a> 6. <a href="https://mp.weixin.qq.com/s?__biz=MzkwOTAyMTY2NA==&mid=2247485664&idx=1&sn=435f9f515a8f881642820d7790ad20ce&scene=21#wechat_redirect" target="_blank">Idea 快捷键大全.pdf</a> ![](https://itsoku.oss-cn-hangzhou.aliyuncs.com/itsoku/blog/article/1/2883e86e-3eff-404a-8943-0066e5e2b454.png)
相关专辑:
Netty专题