美文网首页技术干货程序员
Sentinel之从启动来分析加载过程

Sentinel之从启动来分析加载过程

作者: 橘子_好多灰 | 来源:发表于2018-12-08 15:55 被阅读118次

    之前介绍过dashboard模块也引入的sentinel的核心模块sentinel-core,所以这里通过启动dashboard来分析sentinel在系统初次加载过程中做了什么?

    本文基于:1.3.0-GA版本

    一、启动dashboard项目

    dashboard项目通过CommonFilter过滤器实现对资源的保护的。

    image.png

    启动项目后,访问首页,默认localhost:8080
    在过滤器CommonFilter就会拦截请求的资源,如图。

    image.png

    这个时候就进入到sentinel的核心模块了。

    二、进入ContextUtil

    首先执行ContextUtil静态快内容,如图:


    image.png

    1、首先获取默认的Context名称:sentinel_default_context;Context是一次调用的上下文内容,主要包括:name,entranceNode(调用树资源入口),curEntry(当前实体)等信息,关于这个Context上下文、EntranceNode等后续再介绍。
    2、构建一个EntranceNode节点node。
    3、构建一个跟节点ROOT,并增加一个字节点node;见第三步Constants
    4、把资源信息放到一个 contextNameNodeMap,后面进入资源名称相同直接可以从map中获取。

    三、进入Constants

    Constants是一个常量类,这里我们主要注意的是断点处,如图:

    image.png

    1、在构建一个DefaultNode,用的是new EntranceNode(ResourceWrapper,ClusterNode)方法,
    2、EntranceNode是DefaultNode的子类,
    3、ResourceWrapper是一个资源包装器,这里用的通用的StringResourceWrapper包装器,
    4、构建一个ClusterNode用的是Env类的nodeBuilder的静态变量,通过DefaultNodeBuilder获取。

    四、进入Env

    image.png

    注意到静态块内容,Env类在初始化会加载。来到InitExecutor类

    五、进入InitExecutor

    这个就是Sentinel的加载的核心了。

    image.png

    在doInit中:
    1、有一个initialized原子变量,保证初始化内容只会执行一次
    2、接着ServiceLoader<InitFunc> loader = ServiceLoader.load(InitFunc.class); 这行代码就是通过JDK自带的SDK自带的SPI机制获取InitFunc的实现类了,对SPI机制不熟悉的可以自查资料了解下;
    这里默认自带了4种初始化内容

    image.png
    • CommandCenterInitFunc:命令中心初始化
    • FileDataSourceInit:文件数据源初始化,要这个有效的话,要引入sentinel-demo-dynamic-file-rule模块;并在META-INF/services中加入该类,才可以初始化加载;功能就是把sentinel的规则变量写入到文件中。
    • HeartbeatSenderInitFunc: 心跳发送初始化
    • ParamFlowStatisticSlotCallbackInit :热点参数统计插槽初始话,通过StatisticSlotCallbackRegistry注册

    3、接下来第一个循环就是要初始的Init进行排序,
    4、第二个循环就排序的顺序加载初始化

    image.png

    这里我们先进入到CommandCenterInitFunc中;

    六、进入CommandCenterInitFunc

    image.png

    1、同样是通过SPI加载ComandCenter的实现类,这里用的是SimpleHttpCommandCenter,因为dashboard引入的sentinel-transport-simple-http模块,若是引入netty-http模块则是NettyHttpCommandCenter
    2、然后执行beforeStart()和start()方法

    七、进入SimpleHttpCommandCenter

    先执行beforeStart方法

    image.png

    1、通过CommandHandlerProvider的namedHandlers方法获取所有的CommandHandler,见第八步
    2、并把获取的ComandHandler注册到handlerMap中

    接下来执行start方法
    1、获取机器的核数
    2、创建一个bizExecutor线程池
    3、创建一个serverInitTask线程任务
    4、放入到executor线程池(单个线程)中执行,在个线程中会把HttpEventTask任务放到bizExecutor线程池中的线程处理

    八、进入CommandHandlerProvider

    这里同样通过SPI机制获取实现了CommandHandler的类

    image.png

    可以发现实现ComandHandler有这么多。


    image.png

    1、在for循环中把获取注释的CommandMapping注解的类,并放入Map<String, CommandHandler>这个map中,方便下次直接获取。

    回到SimpleHttpCommandCenter类的beforeStart方法中。

    总结

    1、sentinel在首次资源访问的的过程中SPI机制加载初始化的内容,后续资源进来了不用在加载一遍。
    2、SPI机制sentinel用的很多,但是这个JDK在的SPI加载有个缺点,就是全量加载,很多没有用的功能也加载进来了;可以参考Dubbo的ExtensionLoader进行懒加载。
    3、可以说sentinel首次加载的过程就是InitFunc加载的过程。
    4、这里初始化只分析了CommandCenterInitFunc;至于其它几个:FileDataSourceInitsentinel默认没有用到,
    ParamFlowStatisticSlotCallbackInit热点参数的,还在实践中,
    HeartbeatSenderInitFunc这个就是用来发送心跳的。


    以上内容,若有不当之处,谢谢指正

    相关文章

      网友评论

        本文标题:Sentinel之从启动来分析加载过程

        本文链接:https://www.haomeiwen.com/subject/modqhqtx.html