在线客服
扫描二维码
下载博学谷APP扫描二维码
关注博学谷微信公众号
Java开发中Netty线程模型原理解析,Netty是Java领域有名的开源网络库具有高性能和高扩展性的特点,很多流行的框架都是基于它来构建。Netty 线程模型不是一成不变的,取决于用户的启动参数配置。通过设置不同的启动参数Netty ,可同时支持 Reactor 单线程模型、多线程模型。
Netty线程模型就是Reactor模式的实现,如图:
一、线程组
Netty抽象了两组线程池BossGroup和WorkerGroup,其类型都是NioEventLoopGroup,BossGroup用来接受客户端发来的连接WorkerGroup则负责对完成TCP三次握手的连接进行处理。
NioEventLoopGroup里面包含了多个NioEventLoop管理NioEventLoop的生命周期。每个NioEventLoop中包含了一个NIO Selector、一个队列、一个线程;其中线程用来做轮询注册到Selector上的Channel的读写事件和对投递到队列里面的事件进行处理。
Boss NioEventLoop线程的执行步骤:
(1)处理accept事件与client建立连接, 生成NioSocketChannel。
(2)将NioSocketChannel注册到某个worker NIOEventLoop上的selector
(3)处理任务队列的任务 即runAllTasks。
Worker NioEventLoop线程的执行步骤:
(1)轮询注册到自己Selector上的所有NioSocketChannel的read和write事件。
(2)2处理read和write事件在对应NioSocketChannel处理业务。
(3)#runAllTasks处理任务队列TaskQueue的任务,一些耗时的业务处理可以放入TaskQueue中慢慢处理这样不影响数据在pipeline中的流动处理。
Worker NIOEventLoop处理NioSocketChannel业务时,使用了pipeline (管道),管道中维护了handler处理器链表用来处理channel中的数据。
二、ChannelPipeline
Netty将Channel的数据管道抽象为ChannelPipeline,消息在ChannelPipline中流动和传递。ChannelPipeline持有I/O事件拦截器ChannelHandler的双向链表,由ChannelHandler对I/O事件进行拦截和处理,可以方便的新增和删除ChannelHandler来实现不同的业务逻辑定制不需要对已有的ChannelHandler进行修改能够实现对修改封闭和对扩展的支持。
ChannelPipeline是一系列的ChannelHandler实例,流经一个Channel的入站和出站事件可以被ChannelPipeline 拦截。每当一个新的Channel被创建了,都会建立一个新的ChannelPipeline并绑定到该Channel上,这个关联是永久性的;Channel既不能附上另一个ChannelPipeline也不能分离当前这个。这些都由Netty负责完成,而无需开发人员的特别处理。
根据起源一个事件将由ChannelInboundHandler或ChannelOutboundHandler处理,ChannelHandlerContext实现转发或传播到下一个ChannelHandler。一个ChannelHandler处理程序可以通知ChannelPipeline中的下一个ChannelHandler执行。Read事件(入站事件)和write事件(出站事件)使用相同的pipeline,入站事件会从链表head 往后传递到最后一个入站的handler出站事件会从链表tail往前传递到最前一个出站的 handler,两种类型的 handler 互不干扰。
ChannelInboundHandler回调方法:
ChannelOutboundHandler回调方法:
三、异步非阻塞
写操作:通过NioSocketChannel的write方法向连接里面写入数据时候是非阻塞的,马上会返回即使调用写入的线程是我们的业务线程。Netty通过在ChannelPipeline中判断调用NioSocketChannel的write的调用线程是不是其对应的NioEventLoop中的线程,如果发现不是则会把写入请求封装为WriteTask投递到其对应的NioEventLoop中的队列里面,然后等其对应的NioEventLoop中的线程轮询读写事件时候,将其从队列里面取出来执行。
读操作:当从NioSocketChannel中读取数据时候并不是需要业务线程阻塞等待,而是等NioEventLoop中的IO轮询线程发现Selector上有数据就绪时,通过事件通知方式来通知业务数据已就绪,可以来读取并处理了。
每个NioSocketChannel对应的读写事件都是在其对应的NioEventLoop管理的单线程内执行,对同一个NioSocketChannel不存在并发读写,所以无需加锁处理。
使用Netty框架进行网络通信时,当我们发起I/O请求后会马上返回,而不会阻塞我们的业务调用线程;如果想要获取请求的响应结果,也不需要业务调用线程使用阻塞的方式来等待,而是当响应结果出来的时候,使用I/O线程异步通知业务的方式,所以在整个请求 -> 响应过程中业务线程不会由于阻塞等待而不能干其他事情。
— 申请免费试学名额 —
在职想转行提升,担心学不会?根据个人情况规划学习路线,闯关式自适应学习模式保证学习效果
讲师一对一辅导,在线答疑解惑,指导就业!
相关推荐 更多
JSP四大作用域及请求范围总结
程序员在写代码的时候,难免会遇到作用域的问题,今天我们要谈的也是JSP的四大作用域。本文主要总结了JSP四大作用域page、request、session和application和它们的请求范围。
8369
2019-08-19 17:23:19
Java基础视频教程免费资源分享
Java基础视频教程免费资源分享,Java基础知识比较多,要学习Java语言核心语法、面向对象程序设计、常用API、集合框架、IO流、线程、进程、多线程、并发、并行、同步、异步、线程类常见方法、网络编程、反射技术、常用设计模式、JDK新特性等JavaSE领域的知识。
5885
2020-05-05 16:27:45
MySQL数据库基础知识汇总梳理
本文对MySQL数据库基础知识进行了汇总和梳理,主要内容有认识数据库、常见数据库排行榜、SQL的概念以及DDL操作数据库。希望大家看完之后,能够能够理解数据库的概念,并且能够使用SQL语句操作数据库。
5481
2020-07-03 15:02:31
Sass语言声明和引用变量知识点分享
Sass语言声明和引用变量知识点分享,Sass拥有比其他任何CSS扩展语言更多的功能和特性。Sass几乎可以完全兼容所有版本的CSS。且有无数的框架使用Sass构建,如Compass、Bourbon和Susy。
3037
2021-05-17 10:27:32
Spring框架实现依赖注入操作步骤解析
Dependency Injection是spring框架核心 ioc 的具体实现。程序在编写时通过控制反转把对象的创建交给了spring,但是代码中不可能出现没有依赖的情况。ioc 解耦只是降低他们的依赖关系但不会消除,坐等框架把持久层对象传入业务层而不用我们自己去获取。
3868
2021-05-24 11:31:52