sentinel 整合 gateway 实现网关流控源码流程图
2024-01-02 10:24:07 10 举报
Sentinel整合Gateway实现网关流控的源码流程图主要包括以下几个步骤: 1. 引入Sentinel依赖,配置限流规则。 2. 在Gateway中使用Sentinel提供的API进行限流控制。 3. 当请求到达Gateway时,Sentinel根据配置的规则进行限流判断。 4. 如果请求流量超过限制,Sentinel会拒绝该请求,返回限流提示信息。 5. 如果请求流量未超过限制,Gateway会继续处理请求并返回响应结果。 通过以上步骤,Sentinel可以帮助我们实现对Gateway的流量控制,保证系统的稳定性和可用性。
作者其他创作
大纲/内容
GatewayFlowSlot
解析请求中的参数并与匹配的网关流控的参数 index 对应起来
$D 这个默认值赋值给 arr[size - 1]也就是未设置参数的网关流控规则参数索引对应的值
需要结合GatewayRuleManager.GatewayRulePropertyListener#applyGatewayRuleInternal在加载/更新配置的时候网关流控规则会内部转成 热点参数规则
rule 有设置参数
GatewayApiMatcherManager.getApiMatcherMap().values() .stream() .filter(m -> m.test(exchange)) .map(WebExchangeApiMatcher::getApiName) .collect(Collectors.toSet())
return true
return new Object[0]
只要有一个rule check 不通过抛异常
predSet.add(rulePredicate.test(rule)
没有设置参数的网关流控规则(也就是没有针对请求属性进行配置的规则)并且 hasNonParamRule 为 false说明该资源没有网关流控规则,直接返回 new Object[0] -> 也就是说该 request 没有参数 -> 会传递到 sentinel 的 slot 中
3. 上述判断不满足则继续往下走去解析request 中的参数值并与对应的index 下标对应
for (GatewayFlowRule rule : gatewayRules) { 遍历设置参数的网关流控规则 将参数下表对应的值和 request 参数对应起来}
hasNonParamRule 赋值 true
获取网关流控规则转成的 热点参数规则列表List<ParamFlowRule>
执行 lambda 表达式该 rule 是自定义 API 维度则返回true
执行 lambda 表达式该 rule 资源是route维度则返回true
rule.getParamItem() != null
implements
这里就是会创建一个针对 route 微服务应用维度的限流 entry
解析到的 参数值赋值给 arr[idx]
GatewayRuleManager.getConvertedParamRules(resourceWrapper.getName())
pickMatchingApiDefinitions(exchange)
for (GatewayFlowRule rule : GatewayRuleManager.getRulesForResource(resource)) { 遍历资源对应的所有的网关流控规则,有设置参数的添加到 gatewayRules 中 限流维度匹配的添加到 predSet 中 只要该资源对应的网关流控规则中有一个没有设置参数,则 hasNonParamRule 为 true}
1. !hasNonParamRule && gatewayRules.isEmpty()
ParamFlowChecker#passCheck
遍历结束
执行下个 slot
SentinelGatewayFilter -> GatewayParamParser#parseParameterFor网关过滤器中解析出来的请求的参数数组有两种情况:1. Object[0]: 0个元素的数组2. Object[该资源有未配置参数的流控规则 ? 该资源配置了参数的流控规则的数量 + 1 : 该资源配置了参数的流控规则的数量]最后:不管有几个未配置参数的流控规则,最后这些流控规则的 index 是配置了参数的流控规则的数量 + 1 -> 对应解析出的参数数组的最后一位索引下标且设置了默认值为 $D
rule没有配置参数
1. SentienlGatewayFilter 中解析到的参数数组长度小于等于网关流控规则的参数 index 那么直接返回 true不需要进行 check 了
if (value == null)
if(hasNonParamRule)
Optional.ofNullable(GatewayCallbackManager.getRequestOriginParser()) .map(f -> f.apply(exchange)) .orElse(\"\")
SentinelGatewayFilter#filter
这里就不画了
origin 获取
解析请求中的参数并匹配网关流控规则设置的参数属性匹配成功则返回参数值,匹配失败则返回 $NM 表示没有匹配到该流控规则
2. predSet.size() > 1 || predSet.contains(false)
大部分应该还是 Object[0] 的情况才会进来的假设网关流控规则有 3 个且都配置了参数 -> args.length 为 3rule.getParamIndex() 最大为 2 (因为下标从 0 开始的)
for (ParamFlowRule rule : rules) {遍历热点参数规则并进行资源的限流校验校验通过进入下个 slot,校验不通过抛出热点参数的异常}
GatewayFilter
ParamFlowException
每个匹配的api 分组都会创建一个 自定义 API 维度的限流entry-> 每个 entry 都会走一遍 slot chain
param 赋值给 arr[index]
GlobalFilter
RouteMatchers#antPath:前缀匹配RouteMatchers#exactPath:精确匹配RouteMatchers#regexPath:正则匹配
route 维度必然会走一遍 slot chain如果有 2 个api 分组且都匹配请求,那么就会创建 2个 自定义 Api维度的 entry,每个都会执行一遍 slot chain -> 最终就是走 3 遍 slot chain
执行lambda 验证 rule 的资源维度
1. 路由不为空则创建route 维度的 entry(只要 gateway 配置了 route 那么该 entry 是必然会有的,route 维度的 slot chain 必然会走一遍,但是如果没有给 route 资源配置流控规则、降级规则等那么进入每个 slot 后因为没有获取到该资源对应的规则所以 check 会直接不执行)if (route != null) { 网关路由不为空则创建一个 route 服务应用维度的 sentinel 入口}
predSet大于 1 或者 predSet 中包含 false -> set 是不可重复的,如果数量大于1 说明该资源同时拥有 route 维度和 自定义 api 维度的网关流控规则说明同一资源(资源名称一样)不能同时拥有 route 维度和 自定义 api 维度的网关流控规则否则直接返回 new Object[0] -> 也就是说该 request 没有参数 -> 会传递到 sentinel 的 slot 中
这块看下 sentinel 源码,我在里面还是解析的还是比较详细的
GatewayCallbackManager#setRequestOriginParser静态方法,可以去某个 Bean 初始化的时候自定义设值
3. 正式开始热点参数的限流校验
所有的 rule 都检查通过
限流校验
gatewayRules.add(rule)
2. 参数值为空则直接返回 true不需要进行 check 了
遍历自定义的 API 分组 ApiDefinition -> 获取与该请求匹配的 ApiDefinition 的名称(需要先去 Api 管理菜单中添加 Api 分组 - ApiDefinition -> 该 Api 分组名称就是自定义 API 维度的资源名称)
GatewayParamParser#parseParameterFor
2. 创建 自定义 API 维度的 entry (每个匹配的 api 分组都会创建一个)每个该维度的 entry 也会独立的去走一遍 slot chain
这里只是简单画了下 sentinel 整合 gateway 的一些流程,具体的 sentinel 源码流程以及 sentinel 源码改造和持久化机制(持久化之整合nacos)可以看下这个https://www.processon.com/diagraming/62e250e7637689072ef04ac9
请求路径 和 ApiDefinition 的ApiPredicateItem 进行路径的匹配,匹配成功则返回该 A皮Definition 的名称
if (args.length <= rule.getParamIdx())
0 条评论
下一页