参考文献:极客时间傅健老师的《Netty源码剖析与实战》Talk is cheap.show me the code!

--1主线分两步:

  一:首先在our thread里,如果写在main方法中则就是main thread;

①:创建selector;

②:创建server socket channel;

③:初始化server socket channel;

④:给server socket channel 从boss  group中选择一个NioEventLoop;

  二:boss thread:

⑤:将server socket channel注册到选择的NioEventLoop的selector(上一步创建的selector)

⑥:绑定地址启动

⑦:注册接收连接事件(OP_ACCEPT)到selector上

--2源码演示:

  首先在代码启动的地方加断点,并且在NioEventLoop.java中的openSelector()上也加一个断点(用于验证selector什么时候被创建),如下图:

Debug启动后会进入上图第一个断点,放行后进入openSelector()的这个断点上,通过观察Frames区域可以发现selector是在刚才第一个断点的时候就被创建了,即“EventLoopGroup bossGroup = new NioEventLoopGroup();”的时候:

好的,继续放行之后则回来到开启服务的断点:

不难看出有个sync(),它表示阻塞,也就是说启动本身是个异步的过程,.sync()代表要启动完才能进行下一步;接下来进入bind()方法看看,一直跟进,直到进入doBind();在如图的两个地方加上断点:

上图的“final ChannelFuture regFuture = initAndRegister();”;initAndRegister()实际表示三步:①创建一个server socket channel,②初始化server socket channel,③将server socket channel注册到NioEventLoop的selector上。创建完成之后返回的是regFuture;通过名字“Future”就可以知道它是异步过程;所以上图第一个断点不一定能注册完成,因为注册是丢到NioEventLoop里面去执行去了,所以有个第二个断点:等着注册完成之后来通知再执行bind。然后我们跟进去看看initAndRegister():

不难看出先通过工厂创建后初始化,接着跟进init(channel)方法:挨个下一步可以看到这段代码:

这里的ChannelInitializer一次性,初始化hander,负责添加一个ServerBootstrapAcceptor hander,添加完成后自己就移除了,其中ServerBootstrapAcceptor hander负责接收客户端连接创建连接后,对连接的初始化工作。跳回去之后可以看到:

"ChannelFuture regFuture = config().group().register(channel);"的group()就是boss group,跟进register()之后有这个代码,在图中的register0()这边加个断点:

然后跟进eventLoop.execute()方法:

接着进入startThread();

走到这才是正正的启动线程,接着放行则会执行register0();

再跟进register0()方法

跟进doRegister():

这里不难发现它真正在处理了,然后先跳回去,下面这图就是通知我们成功了

继续往下走则会到之前打的一个断点(doBind0());

然后继续跟进:

在channel.bind()加一个断点:然后紧接着跳过来在进入bind()方法:

可以看到pipeline.bind();Netty是串行化的操作,pipeline里面有各种各样的hander,除了上图截图显示的hander,每个pipeline都有head和tail 的hander;如下显示:

这里我们跳到head的hander;操作如下:

跳过来之后查找bind()方法如图,

找到之后在unsafe.bind()加一个断点:

跳过来进入bind()方法看看:

可以看到这一步:do开头的几乎都是表示执行!在跟进去看看:

这时候就能看到bind了,然后继续

这里的就是绑定后开始激活,在pipeline.fireChannelActive()加一个断点,跳过来后:

和之前一样,跳到head上;然后查找ChannelActive();

打上断点如图,接着跳过来,其中readIfIsAutoRead()就是注册读事件,读包括:创建连接、读数据,这里指的是创建连接。跟进方法:

继续跟进:

能看出pipeline.read();这时候打开之前跳转过来的pipeline的head里找到read();

加个断点接着跳过来,这里unsafe.beginRead();实际上就是注册OP_ACCEPT/OP_READ事件;创建连接或者读事件。接着跟进:

实际它是调用的doBeginRead();

继续跟进:

走到这里就开始注册OP_ACCEPT=16。

--3总结:启动服务的本质:

  Selector selector = sun.nio.ch.SelectorProviderImpl.openSelector();

  ServerSocketChannel serverSocketChannel = provider.openServerSocketChannel();

  selectionKey = javaChannel().register(eventLoop().unwrappedSelector(),0,this);

  javaChannel().bind(localAddress,config.getBacklog());

  selectionKey.interestOps(OP_ACCEPT);

Selector是在new NioEventLoopGroup()(创建一批NioEventLoop)时创建的

第一次Register并不是监听OP_ACCEPT,而是0;

  selectionKey = javaChannel().register(eventLoop().unwrappedSelector(),0,this);

最终监听OP_ACCEPT是通过bind完成后的fireChannelActive()来触发的。

NioEventLoop是通过Register操作的执行来完成启动的

类似ChannelInitializer,一些Hander可以设计成一次性的,用完就移除,比如授权。

我只想做的更好,仅此而已。

Netty源码剖析-启动服务的更多相关文章

  1. Netty源码剖析-关闭服务

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:  ----源码: 先在服务端加个断点和修改下代码:如 ...

  2. Netty学习笔记(三)——netty源码剖析

    1.Netty启动源码剖析 启动类: public class NettyNioServer { public static void main(String[] args) throws Excep ...

  3. Netty源码剖析-发送数据

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! 开始之前先介绍下Netty写数据的三种方式: ①:write:写到一 ...

  4. Netty源码剖析-业务处理

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:worker thread 触发pipeline.fi ...

  5. Netty源码剖析-接受数据

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线:worker thread ①多路复用器(Select ...

  6. Netty源码剖析-构建链接

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线: 和启动一样也是有两个线程完成的,boss threa ...

  7. Netty源码剖析-断开连接

    参考文献:极客时间傅健老师的<Netty源码剖析与实战>Talk is cheap.show me the code! ----主线: ----源码: 在NioEventLoop的unsa ...

  8. 二 分析easyswoole源码(启动服务)

    前文连接,阅读的时候最好参照EasySwoole2.1.2的源码 $inst->run();//启动服务 这里实际调用的是Core的start方法ServerManager::getInstan ...

  9. Netty 源码剖析之 unSafe.write 方法

    前言 在 Netty 源码剖析之 unSafe.read 方法 一文中,我们研究了 read 方法的实现,这是读取内容到容器,再看看 Netty 是如何将内容从容器输出 Channel 的吧. 1. ...

随机推荐

  1. gitlab高可用模式

    高可用模式 企业版 社区版 我们这里说一下成本比较低的主备模式,它主要依赖的是DRBD方式进行数据同步,需要2台ALL IN ONE的GitLab服务器,也就是通过上面安装方式把所有组件都安装在一起的 ...

  2. ICEM—二维混合网格对齐节点

    原视频下载地址: https://pan.baidu.com/s/1bpnjfT9 密码: jeuv

  3. 冲刺总结——Day7

    [今日进展] 代码整合 码云链接:https://gitee.com/jxxydwt1999/20175215-java/tree/master/GoldPoint 功能测试 注册 登录 运行 [燃尽 ...

  4. Springboot使用zuul进行负载均衡

    完整项目代码地址参考:https://github.com/SimonHu1993/SpringbootZuul 1.这里我们使用Eureka来作为服务的注册与发现中心,首先看看Eureka clie ...

  5. arcpy.UpdateCursor和arcpy.da.UpdateCursor计算面积时间的比较

    arcpy.UpdateCursor ####################### import arcpy from arcpy import env import os import sys f ...

  6. P3015 [USACO11FEB]最好的括号Best Parenthesis

    P3015 [USACO11FEB]最好的括号Best Parenthesis 题解 一定要开 long long !!! 通过阅读英文题面我们知道所给出的字符串是已经匹配好的,所以我们只是计算就好了 ...

  7. 设置Win10默认启动的Linux子系统版本,启动指定Linux发行版

    设置Win10默认启动的Linux子系统版本,启动指定Linux发行版   MS酋长一年前已经与大家分享了启用“适用于Linux的Windows子系统(WSL)”的方法,但当时所能安装的只有由Cano ...

  8. 数据分析 - sql 业务相关练习题

    数据库    userinfo , orderinfo 表 两个 userId 彼此对应 题目 解题 不同月份的下单人数 用户在同一个月份会下多个单,这里进行去重 未支付的脏数据去除 统计用户三月份的 ...

  9. 数据分析 - Excel 配色, 绘图, 技巧

    美学 配色 画图本身是美学的展示, 出色的配色是必须的 虽然本身美学并不是数据分析的必要, 但是也不能太low 如果做的太丑展示也是很尴尬 配色网站 点击这里 配置 现版本的 excel 中已存在较为 ...

  10. 【如何设置IIS程序池的回收时间,才能最大程度的减少对用户的影响?】

    作为.Net开发人员,其实对IIS的应用程序池知之甚少,前段时间被问到一个问题: 对于互联网web应用,如何在用户毫无感知的情况下回收程序池?(对用户产生最小的影响) 简单理解IIS应用程序池 应用程 ...