您好!
欢迎来到京东云开发者社区
登录
首页
博文
课程
大赛
工具
用户中心
开源
首页
博文
课程
大赛
工具
开源
更多
用户中心
开发者社区
>
博文
>
Java NIO 图解 Netty 服务端启动的过程
分享
打开微信扫码分享
点击前往QQ分享
点击前往微博分享
点击复制链接
Java NIO 图解 Netty 服务端启动的过程
ca****
2023-08-17
IP归属:北京
5600浏览
# 一.启动概述 了解整体Netty常用的核心组件后,并且对比了传统IO模式。在对比过程中,找到了传统IO对应Netty中是如何实现的。最后我们了解到在netty中常用的那些组件。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-43dOOebh88PoAdVXz.png) 本文在了解下这些核心组件的前提下,进一步了解组件如何在整个服务器启动过程如何被创建,如何组件之间配合来使用。首先也是先了解下大概服务端的启动过程,并且在了解过程中我们带着自己的问题去在学习过程中探寻答案。 ## 1.1 启动概述 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-43woBcWXHJB43n0iFm.png) ## 1.2 启动问题 0.netty服务端启动是如何设置非阻塞模式的? 1.服务端启动后事件是如何注册到selector上? # 二.启动详述 ## 2.1 channel 创建 还是一样首先在channel创建过程大概有哪些过程 - i: bind - ii: initAndRegister - iii: 默认构造函数创建channel 具体调用关系 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-44IU11TKLbm0qMskHY.png) 时序图中从1,2,3步都好理解。 ### 2.1.1 创建channelFactory 从类的反射得到channel这里是一个关键点需要说明: ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-44qiSTY07gsbYkOyf.png) 图中直接使用channelFactory来实现了channel的实例化.那么就按图索骥这个channelFactory是什么时候赋值的。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-45O8hpRq5757f9uawZU.png) 图中我们一步步找到channelFactory的路径。我们再看第三步是谁调用了 channel(Class<? extends C> channelClass) 创建了channelFactory。最后发现我们在bootstrap设置channel属性的时候设置了channelFactory。 ![在这里插入图片描述](https://img-blog.csdnimg.cn/20210613115604650.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5mYW5nbGluY2Zs,size_16,color_FFFFFF,t_70) 走到这里我们才真正进入知道在bootstrap设置NioServerSocketChannel。并利用NioServerSocketChannel创建。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-46J389DhfNXrZa8bkU.png) 上述步骤我们小结一下。通过设置bootstrap的Channel属性来设置服务端NioServerSocketChannel生成了channelFactory。channelFactory 来主动调用传入的class来构造channel。 ### 2.2.2 NioServerSocketChannel默认构造函数创建Channel 从上图中我们知道该构造工厂是调用类的构造函数来进行初始化,通过代码中我们知道构造类为NioServerSocketChannel。那么就看下NioServerSocketChannel构造过程。 先上来还是看下整体步骤: ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-47Cup7Izljt711mS21.png) 通过默认的newSocket方法创建了jdk底层的channel,然后通过Channel的配置了channel的id,对应channel底层的读写unsafe组件,channel对应的逻辑处理pipeline, 最后通过configureBlocking设置channel为非阻塞模式【回答了我们第一个问题】。 第三步:通过channelConfig设置一些tcp层面的设置 至此channel创建完成 ## 2.2 channel 初始化 通过上面2.1 整个channel已经创建完成。第二大步在创建channel的基础上,给channel做一些属性配置。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-47WoxbwIwiflPOoUK.png) ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-48MECPtM0VpwZeJRV.png) 上图设置用的属性 对应到代码中 为如下的代码 ![](https://img-blog.csdnimg.cn/20210613135700787.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2NoZW5mYW5nbGluY2Zs,size_16,color_FFFFFF,t_70) 这里均为一些自己的属性和配置的设置,至此channel的创建和初始化完成。这里的配置用以客户端新建连接时进行设置。 ## 2.3 selector 注册 还是先整体看下 整个 selector 流程,是如何将channel注册到selector上。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-49JjmCHEPmaZFEzQU.png) ps:以上代码流程需要一层层通过断点方式进行跟踪。 第一步:AbstractBootStrap register 入口 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-49Fxh498uYgLVKTsQs.png) 以上的步骤完成channel的创建和初始化,通过initAndRegister内部方法来实现selector挂载. 第二步:调用 io.netty.channel.MultithreadEventLoopGroup#register(io.netty.channel.Channel) register方法中通过next方法获取下一个可以调用EventLoop来调用它的register方法 第三步:调用 io.netty.channel.SingleThreadEventLoop#register(io.netty.channel.Channel) 调动channel.unsafe.register 方法获取channel底层操作,并调用unsafe的register方法 第四步:通过调用abstract Nio Channel 将channel注册到eventLoop的selector中【第二个问题的答案】,并将当前channel作为attache与socket channel关联。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-50EKmpXYnUBit0o6E.png) 完成对应的selector 和 channel 绑定之后如果有相应的事件回调会进行事件回调操作,这里需要的话需要继承ChannelInboundHandlerAdapter中对应的方法channelRegistered, channelActive。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-50HbzSOsNdQyqy7wO.png) 至此nio channel 通过java 底层的socketchannel绑定 到指定的selector ,完成selector与niochannel 的注册过程。 ## 2.4 端口绑定 基本步骤 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-5056eX8Jpr8TeZbTiO.png) ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-51FNQCM717g7IBJ11u9.png) 第一步:底层端口channel绑定 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-51XVseTDJsDAU0EFB.png) 第二步:最终调用AbstractNioChannel doBeginRead方法。 激活channel 并向selector 注册 read 事件。 ![](https://s3.cn-north-1.jdcloud-oss.com/shendengbucket1/2023-07-17-11-52COHhk527U6VNE0sq.png) # 三 .总结 整体了解到netty服务端的启动过程。 - 1.通过NioServerSocketChannel的channelFactory创建channelFactory方法 - 2.channelFactory 通过反射调用nioServerSocketChannel构造函数。创建channel对象 - 3.channel通过NioServerSocketChannelConfig将自定义的option,attr,handler设置完成。 - 4.abstract Nio Channel调用register方法实现selector和channel的绑定 - 5.最终调用java channel 进行端口绑定并向selector 注册read事件 整体netty服务端启动完成。
上一篇:一种通用的业务监控触发方案设计
下一篇:Spring缓存是如何实现的?如何扩展使其支持过期删除功能?
ca****
文章数
1
阅读量
140
作者其他文章
01
Java NIO 图解 Netty 服务端启动的过程
一.启动概述了解整体Netty常用的核心组件后,并且对比了传统IO模式。在对比过程中,找到了传统IO对应Netty中是如何实现的。最后我们了解到在netty中常用的那些组件。本文在了解下这些核心组件的前提下,进一步了解组件如何在整个服务器启动过程如何被创建,如何组件之间配合来使用。首先也是先了解下大概服务端的启动过程,并且在了解过程中我们带着自己的问题去在学习过程中探寻答案。1.1 启动概述1.2
ca****
文章数
1
阅读量
140
作者其他文章
添加企业微信
获取1V1专业服务
扫码关注
京东云开发者公众号