Sentinel持久化源码分析
2022-06-03 11:29:14 1 举报
Sentinel持久化源码分析
作者其他创作
大纲/内容
以流控规则为例dataSourceName : flow-rules-sentinel-nacos-datasourcebeanClass: NacosDataSourceFactoryBean
spring webmvc 的逻辑
Sentinel Dashboard
BlockException 异常处理
用于控制是否收敛context,将其配置为false,即可根据不同的url进行链路限流。webContextUnify 为true,统计入口为 sentinel_web_servlet_context,导致链路限流不生效
微服务A
implements
微服务启动
SimpleHttpCommandCenter.ServerThread#run
加载配置
FlowRuleManager.register2Property(rds.getProperty())
创建NacosDataSource对象
this.configService = NacosFactory.createConfigService(this.properties)
T newValue = loadConfig()
创建配置监听器
FetchActiveRuleCommandHandler#handler
可读数据源注册到FlowRuleManager ,这样当规则发生变化时,就会更新规则到内存中
自定义BlockException异常处理
applicaion.yml 配置的规则数据源为nacosspring: application: name: sentinel-application cloud: nacos: discovery: server-addr: 127.0.0.1:8848 sentinel: transport:# sentinel控制台地址 dashboard: 127.0.0.1:8080# 指定应用与sentinel控制台交互的端口,应用本地会起一个该端口占用的 HttpServer port: 8719# 控制是否收敛context;将其配置为false 即可根据不同的url 进行链路限流 web-context-unify: false datasource: flow-rules: nacos: server-addr: 127.0.0.1:8848 data-id: ${spring.application.name}-flow-rules group-id: SENTINEL_GROUP data-type: json rule-type: flow
FlowRuleManager.register2Property(dataSource.getProperty())
3.配置中心配置文件发生变更监听器就会执行回调方法,更新配置规则到内存
SentinelProperty
以流控规则为例
Sentinel Dashborad
初始化 AutoRefreshDataSource扩展自动更新功能
Sentinel 客户端
SentinelDataSourceHandler#afterSingletonsInstantiated
socket 事件执行线程
InMemoryRuleRepositoryAdapter#save
解析配置,并更新到内存
规则缓存
解析配置
判断ruleType
如果是流控规则
SentinelWebInterceptor
给 DynamicSentinelProperty 配置 FlowPropertyListener
获取到Nacos配置中心服务
target = urlCleaner.clean(target)
发布规则
T newValue = NacosDataSource.this.parser.convert(configInfo); getProperty().updateValue(newValue)
DynamicSentinelProperty#updateValue(rules)
Sentinel Client监听端口
流控规则的属性监听器
改造Sentinel Deshboard 将规则发布到配置中心
getProperty().updateValue(newValue)
查看流控规则列表
是
InitExecutor.doInit()
currentProperty.removeListener(LISTENER); property.addListener(LISTENER); currentProperty = property;
HandlerInterceptor
handleFlowRules
FactoryBean
如果 dataSource 不为空
loadInitialConfig()
ReadableDataSource
sentinel-datasource-extension.jar 包中实现
httpMethodSpecify 默认为false
Machine 1
Filter
根据dataSourceName 注册BeanClass ylNacosDataSourceFactoryBean的BeanDefinition
注意: 不同的规则配置解析需要对应的解析器,否则可能导致配置规则不生效
不为空
创建资源上下文
4.更新rules
//创建文件存储目录 RuleFileUtils.mkdirIfNotExits(PersistenceRuleConstant.STORE_PATH); //创建文件存储文件 RuleFileUtils.createFileIfNotExits(PersistenceRuleConstant.RULES_MAP)
初始化CommandCenter
parseOrigin(request)
实现
获取所有的machineRules流控规则
异步设置流控规则
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(dataSourceProperties.getFactoryBeanName())
CtSph#entryWithPriotiry
1.用户通过控制台添加规则
sentinel datasource
FileWritableDataSource#write
原始模式
UrlCleaner
RuleManager
根据ruleType注册到不同的规则管理器
checkEntityInternal(entity)
更新配置到内存中
parser.convert(conf)
repository.save(entity)
正常逻辑
将流控规则的写数据源注册到WritableDataSourceRegistry 的flowDataSource
获取文件最后修改的时间,并加载文件
FileDataSourceInit#init
degrade
flowRules.clear(); flowRules.putAll(rules)
Machine 3
异常逻辑 BlockException 的处理
通过SPI机制获取到SimpleHttpCommandCenter 对象
保存流控规则
getProperty().updateValue(newValue)
commandCenter.beforeStart()
DynamicRuleProvider
String type = request.getParam(\"type\"); String data = request.getParam(\"data\");
根据DataSourceName,利用FactoryBean获取到对应规则的NacosDataSource对象
通信模块
extends
this.configListener = new Listener() {}
CommandHandler
创建规则存储文件
DegradeRuleManager.register2Property(dataSource.getProperty())
远程配置中心(nacos、zk)
将可写数据源注册到 transport 模块中 WritableDataSourceRegistry 中这样收到控制台推送的规则时,sentinel 客户端会先更新到内存,然后将规则写入到文件中
initNacosListener()
更新内存
获取上下文context
flow
Sentinel Dashboard 推送规则,发起post请求http://192.168.203.203:8720/setRules
startTimerService()
写入数据源
检查请求参数,不满足条件直接返回
2.推送规则
Sentine Dashboard 发布规则适配Nacos
this.parser = parser; this.property = new DynamicSentinelProperty<T>();
原始模式:如果不做任何修改,Dashboard的推送规则方式是通过api将规则推送至客户端并更新到内存中,这种做法的好处是简单,无依赖.坏处是应用重启规则就会消失,仅用于简单测试,不能用于生产环境
加载流控规则
List<FlowRuleEntity> rules = flowRuleNacosProvider.getRules(app)
当dataId的数据发生变化后,就会回调listener
/v1/flow/rules
flowDataSource = datasource
从nacos配置中心读取dataId的配置
Machine 2
sentinel 系统初始化的处理逻辑
executor.submit(new ServerThread(serverSocket))
spring-cloud-alibaba-sentinel-datasource-2.2.5.RELEASE.jar
dataSource.write(value)
6.监控线程会周期性监控本地文件,当本地文件发生变更,就会触发监控逻辑,将变更的配置更新到内存中
开启服务线程
font color=\"#f44336\
UrlBlockHandler
HttpEventTask eventTask = new HttpEventTask(socket); bizExecutor.submit(eventTask);
定义通用Bean属性
Servlet的过滤器
lookProcessChain(resourceWrapper)
SmartInitializingSingleton
AbstractSentinelInterceptor#preHandle
FlowRuleManager.loadRules(flowRules)
利用InitFunc扩展实现FileDataSourceInit 初始化逻辑:当用户访问 sentinel 资源时,会初始化此模块,从本地文件加载sentinel规则。当文件配置发生变更时,利用读数据源监听配置规则的变化,将配置更新到内存。当sentinel控制台推送规则时,利用写数据源将配置更新到文件中
用户新增流控规则
4.将规则更新地本地文件,需要实现WritableDataSource
this.lastModified = file.lastModified(); firstLoad();
不存在CommonFilter
CommandCenterInitFunc#init
WebMvcConfigurer
解析资源的请求来源origin
从flowRules中获取流控规则,然后响应给 sentinel dashboard
NacosDataSource 实现原理
webContextUnify默认是true
AbstractDataSource
推模式 远程配置中心(Nacos、Zookeeper等)
循环执行initList的init方法
在单一固定线程池提交任务executor = Executors.newSingleThreadExecutor( new NamedThreadFactory(\"sentinel-command-center-executor\"))
3.更新到内存中
implement
dataSourceProperties.postRegister(newDataSource)
实现SmartInitializingSingleton的接口后,当所有非懒加载的单例Bean都初始化完成后,Spring的IOC容器会回调该接口的 afterSingletonsInstantiated 方法
font color=\"#000000\
type = flow处理流控规则
spring-cloud-starter-alibaba-sentinel-2.2.5.RELEASE.jar\\META-INF\\spring.factories
registerCommands(handlers)
Converter
从Nacos配置中心拉取配置
new Thread(serverInitTask).start()
根据type类型处理不同的规则
serverInitTask 的 run 方法
清掉内存中的规则数据
授权规则的扩展点,来源访问控制根据资源的请求来源(origin) 限制资源是否通过
RequestOriginParser
推模式:生产环境下一般更常用是push械的数据源。对于push模式的数据源,如远程配置中心zookeeper、nacos 等,推送的操作不应由sentinel客户端进行,而应该经控制台统计进行管理,直接进行推送,数据源仅负责获取配置中心推送的配置更新到本地。因此推送规则正确做法应该是 配置中心控制台/Sentinel控制台 --> 配置中心 -->Sentinel数据源 --> sentinel,而不是经Sentinel 数据源推送至配置中心。
循环解析InitFunc实现类封装成OrderWrapper对象并排序
如果是修改规则, Sentinel Client 处理 setRules
开启线程监控本地文件最后修改的时间,周期为3秒,线程前辍为 sentinel-datasource-auto-refresh-task
DispatcherServlet#doDispatch
chain.entry
为dataId添加监听器
创建流控规则的读数据源FileRefreshableDataSource
改造Sentinel Dashboard 从配置中心拉取规则
AbstractDataSource newDataSource = (AbstractDataSource) this.beanFactory.getBean(dataSourceName)
DynamicRulePublisher
获取流控规则的文件路径
allRules.clear(); machineRules.clear(); appRules.clear();
清除内存中旧的流控规则保佑新的流控规则
for循环保存规则到内存中
loadConfig(readSource())
解析 Sentinel Dashboard 发送过来的请求,获取请求的命令
注意:需要引入 sentinel-web-servlet jar包,微服务没有引入此依赖,不会经过CommonFilter
http://127.0.0.1:8030/sentinel/test1?age=1
builder.addPropertyReference(\"converter\
@Bean
WritableDataSource
发布规则到Nacos配置中心
可读数据源,顶层接口
Listener#receiveConfigInfo
调用api /v1/flow/rule请求参数被封装为FlowRuleEntiry
Nacos Dashboard
1.创建了一个cpu核数相等的固定线程池,用来作业务线程池2.开启服务线程创建ServerSocket绑定端口,默认8719,实时监听sentinel-dashboard 发送的请求
RuleRepository
SentinelWebAutoConfiguration
FileRefreshableDataSource#readSource
sentinel 核心逻辑,定义当前要保护的资源
repository.saveAll(rules)
以流控规则为例,处理流控规则
NacosDataSourceFactoryBean#getObject
FlowControllerV1#apiQueryMachineRules
获取所有规则Sentinel Client 处理getRules
for (PropertyListener<T> listener : listeners) { listener.configUpdate(newValue); }
遍历propertyMap key value 转化为BeanDefinitionBuilder属性
getServerSocketFromBasePort(port)
获取到ProcessorSlot chain
CommonFilter#doFilter
拉模式:pull模式的数据源(如本地文件、RDBMS等) 一般是可写入的。使用时需要在客户端注册数据源,将对应的读数据源注册到对应的RuleManager,将写数据源注册至transport的 WritableDataSourceRegistry中,首先Sentinel控制台通过api将规则推送至客户端并更新到内存中,接着注册的写数据源会将新的规则保存到本地文件中。使用pull模式的数据源时一般不需要对Sentinel控制台进行改造。这种实现方法好处是简单,坏处是无法保证 监控数据的一致性
取application.yml 配置的 converterClass 值并定义成Bean
Sentine Dashboard 获取规则适配Nacos
第6步如何实现 ?这种方式属于pull 模式,FileRefreshableDataSource 会周期性(3秒)读取文件获取规则,当文件有更新时会及时发现,并将规则更新到内存中
获取规则类型和数据类型用于判断规则类型,包括: 流控、降级、授权、系统规则
微服务接入Sentinel Dashboard 控制台启动
注意:不同的规则需要配置对应的解析器,否则可能导致配置规则不生效
通过request获取来源标识
持久化到本地文件
解析请求,获取/sentinel/test1?age=1 作为资源名
根据命令找到对应的处理器
String flowRulePath = PersistenceRuleConstant.RULES_MAP.get(PersistenceRuleConstant.FLOW_RULE_PATH)
拉模式 本地文件持久化
用户修改流控规则
FlowControllerV1#apiAddFlowRule
注册dataSourcer 的property到RuleManager
保存所有的流控规则
DefaultBlockExceptionHandler#handler
Sentinel Dashboard 发起Get请求http://192.168.203.203:8720/getRules?type=flow
ReqeustOriginParser的实现类想要生效需要交给WebCallbackManager管理
WritableDataSourceRegistry.registerFlowDataSource(wds)
SentinelApiClient#executeCommand
BlockExceptionHandler
用户发起调用请求
注册所有的CommandHandler 到 CommandCenter的handlerMap 中
创建ServerSocket并绑定端口,端口会从8719开始,如果占用+1
ContextUtil.getContext()
FlowPropertyListener#configUpdate
RequestOriginParser originParser = WebCallbackManager.getRequestOriginParser()
5.用户修改本地规则存储文件
CommandResponse.ofSuccess(JSON.toJSONString(FlowRuleManager.getRules()))
save(rule)
是否自定义规则转换器 ?DATA_TYPE_FIELD.equals(propertyName)
w.func.init()
PropertyListener
写数据源接口
commandCenter.start();
CommandHandlerProvider.getInstance().namedHandlers()
Env
InitFunc
通过SPI梅机制加载sentinel相关依赖包下META-INF/services/下所有InitFunc实例类
返回流控规则列表
此处扩展点,推送规则可以直接发布到Nacos配置中心
ServiceLoaderUtil.getServiceLoader(InitFunc.class)
调用 addInterceptors 方法,注册拦截器
originParser.parserOrigin(request)
第一次调用,Env初始化阶段执行静态代码块
while( true) 死循环监听当前端口
获取所有的流控规则
executeCommand(new HttpGet(urlBuilder.toString()))
protected boolean isModified() { long curLastModified = file.lastModified(); if (curLastModified != this.lastModified) { this.lastModified = curLastModified; return true; } return false; }
Spring webmvc 逻辑
isModified()
implemets
本地规则存储文件
遍历NacosDataSourceProperites属性转化为Map
CommandCenterProvider.getCommandCenter()
将可读数据源注册到 FlowRuleManager 这样当规则文件发生变化时,就会更新规则到内存
保存到内存中。存入三个map : allRules ,matchineRules ,appRules
Spring容器初始化所有的非懒加载单例Bean之后 调用
创建写流控规则数据源 FileWritableDataSource
factoryBean 为 NacosDataSourceFactoryBean,在微服务启动时加载SentinelAutoConfiguration Bean 时,类上有此注解@EnableConfigurationProperties(SentinelProperties.class),将SentinelProperties定义到Bean,会检测DataSourcePropertiesConfiguration Bean,根据appilication.yml 配置的动态数据源为nacos,会加载DataSourcePropertiesConfiguration类,类的空参构造函数指定了 NacosDataSourceFactoryBeanpublic NacosDataSourceProperties() {super(NacosDataSourceFactoryBean.class.getName());}
解析数据为流控规则数组
CommandHandler<?> commandHandler = SimpleHttpCommandCenter.getHandler(commandName)
AutoRefreshDataSource
可读数据源顶层接口
判断是否为资源添加http method 作为前辍,比如 { GET:/sentinel/test1?age=1
更新规则配置到内存
response = ModifyRulesCommandHandler#handler
初始化nacos监听器
HttpEventTask#run
String commandName = HttpCommandUtils.getTarget(request)
被修改过
用新规则替换旧规则,并通知所有属性监听器回调configUpdata方法(前提:当新值不等于旧值)
用来和Sentinel控制台交互的处理器
收藏
0 条评论
下一页