专栏首页瓜农老梁Sentinle集群流控【源码笔记】

Sentinle集群流控【源码笔记】

前言

本文从集群流控概览入手,按照概览的步骤逐步分析各个步骤的源码实现过程。由于集群流控中token server可以是独立部署也可以是使用内嵌模式(即集群应用中的其中一个作为token server)。本文主要以内嵌模式为主。

一、集群流控概览

1.集群流控入口

FlowSlot#checkFlow入口,由FlowRule.clusterMode来设置是否为集群流控,默认false。

2.集群流控流程

说明

@1 TokenService初始化。通过SPI方式获取TokenService,client位于模块sentinel-cluster-client-default的META-INF,默认为DefaultClusterTokenClient;server位于sentinel-cluster-server-default模块的META-INF,默认为DefaultEmbeddedTokenServer;0表示client,1表示server

@2 降级为单机流控。在没有找到TokenService时,降级为单机流控由ClusterFlowConfig参数fallbackToLocalWhenFail决定,默认true

@3 流控规则ID,全局唯一标识

@4 client与server交互过程。client向server请求token,server端处理client请求,使用netty通信

@5 处理返回结果TokenResult

@6 集群流控失败,默认降级为单机流控

类图

二、TokenService初始化

TokenService初始化的初始化由client/server两部分构成。

1.DefaultClusterTokenClient初始化

@1 注册server变更观察者,在server变更时回调changeServer方法,此处可以借鉴如何使用观察者模式。

调用时机 下面以示例中给出的例子为入口切入,观察server变更时的回调流程。

示例中使用动态数据源,在配置变更后执行getProperty().updateValue(newValue)让规则生效。

ClusterClientConfigManager通过静态方法clientAssignProperty注册ClientAssignPropertyListener,监听ClusterClientAssignConfig的变更,主要是server地址和端口的变更。

ClusterClientAssignConfig配置

serverHost:server地址
serverPort:server端口

clientConfigProperty注册ClientConfigPropertyListener监听ClusterClientConfig的变更,主要是超时时间的变更。

ClusterClientConfig配置

requestTimeout:请求超时时间

重新连接server

小结:client初始化时注册观察者,在server配置(server地址与端口)变更时通过netty重新连接到新的server地址。

@2 初始化新连接,此处并未真正与server建立连接

说明:通过ClusterStatePropertyListener进行状态变更时触发与server的连接;ClusterStatePropertyListener在ClusterStateManager初始化时被添加到stateProperty,主要负责client、server角色的切换。

下面示例demo中,通过监听动态配置,来动态切换client与server,判断逻辑见下图备注。

小结:监听client/server的动态配置,ClusterStatePropertyListener负责client/server的状态切换,即:如果本节点是server被变更为client,则先关闭server在启动client;反之同理。0表示client,1表示server,-1表示未启动。

2.DefaultEmbeddedTokenServer初始化

DefaultEmbeddedTokenServer启动时使用SentinelDefaultTokenServer。

@1 注册观察者,通过动态数据源(zk、nacus等)监听serve端通信配置ServerTransportConfig配置的变更,有变更时重新启动server。

ServerTransportConfig配置信息

port:端口号
idleSeconds:连接空闲时间,默认为600秒,超过会关闭连接

更新ServerTransportConfig生效由ClusterServerConfigManager#ServerGlobalTransportPropertyListener负责,用法见示例:

@2 初始化集群流控server,使用netty通信

三、client/server交互

1.client发送令牌请求

@1 构造请求参数FlowRequestData

flowId:流控规则ID全局唯一标识
count:需要的令牌数量,例如:QPS请求数
priority:优先级,如果当前时间窗口令牌不够,是否预占用下个时间窗口的令牌,默认false。

@2 通信通过netty向server端请求,返回结果TokenResult参数

status:返回状态,见TokenResultStatus枚举类。
remaining:集群流控剩余令牌的数量
waitInMs:当prioritized设置为true时,下个时间窗口分配令牌,需要等待的时间,单位毫秒
attachments:保留扩展字段,未使用

@3 记录错误日志,日志文件为sentinel-cluster-client.log

2.server处理令牌请求

处理请求入口

处理请求过程

@1 请求允许通过尝试,GlobalRequestLimiter负责执行。当监听到namespace有新增时,ServerNamespaceSetPropertyListener#configUpdate更新生效。

通过namespace获取全局RequestLimiter,默认10个采样窗口,统计区间为1秒。

ServerNamespaceSetPropertyListener更新过程

@1 集群流控为嵌入模式,默认将appName加入namespace
@2 将过期失效的namespace流控规则移除
@3 构建namespace、flowId、FlowRule、flowIdSet在缓存中的关系以及为每个flowId准备集群流控统计ClusterMetric,详见:FlowRulePropertyListener#applyClusterFlowRule
@4 构建namespace、flowId、ParamFlowRule、flowIdSet在缓存中的关系以及为每个flowId准备集群热点参数流控统计ClusterParamMetric,详见:ParamRulePropertyListener#applyClusterParamRules
@5 RequestLimiter初始化,GlobalRequestLimiter负责集群全局统计限速判断

@2 根据flowId获取对应的集群流量统计信息ClusterMetric @3 计算剩余的允许通过的令牌数 = 允许通过的令牌数阈值 * 限制倍数 - 已经使用的令牌 - 本次需要的令牌

允许通过的令牌数阈值

exceedCount:限制倍数,默认1.0,可由ServerFlowConfig#exceedCount设置
latestQps:已经使用的令牌
acquireCount:本次需要的令牌

@4 剩余令牌大于等于0,允许通过返回OK

@5 如果设置了优先级prioritized,会占用下个时间窗口的令牌

@6 无令牌可用,统计被阻塞请求并记录日志

@7 返回阻塞结果BLOCKED

四、返回结果处理

说明

OK:值为0,正产放行。允许通过

SHOULD_WAIT:值为2,当设置prioritized=true时预占下个时间窗口令牌需要等待的时间。允许通过

NO_RULE_EXISTS:值为3,缓存中根据flowId找不到FlowRule。不允许通过抛出FlowException

BAD_REQUEST:值为-4,flowId为null或者小于0,通过的请求count小于0,即入参问题。不允许通过抛出FlowException

FAIl:值为-1,内部发生异常了。不允许通过抛出FlowException

TOO_MANY_REQUEST:值为-2,本次请求直接超过设置允许的阈值,被拦回。不允许通过抛出FlowException

BLOCKED:值为1,请求被阻塞。不允许通过抛出FlowException

本文分享自微信公众号 - 瓜农老梁(gh_01130ae30a83),作者:梁勇

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2020-10-11

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Sentinel集群流控参数说明

    当流控规则FlowRule#clusterMode设置为true时,开启集群流控。集群流控ClusterFlowConfig属性如下。

    瓜农老梁
  • gRPC服务端启动流程走查

    小结: @1 构建监听地址SocketAddress @2 将service注册到缓存 @3 Server构建 @4 服务端启动

    瓜农老梁
  • RocketMQ消息轨迹【源码笔记】

    在一个集群中可以配置一台机器专门负责消息轨迹的收集工作,该台机器上配置traceTopicEnable = true,borker启动的时候自动创建默认轨迹to...

    瓜农老梁
  • 走近源码:Redis的启动过程

    当我们对不断加深对某一项技术的了解时,一定会在一个特定的时间对它的实现方式产生兴趣。没错,这就是我现在的状态,所以,多年没有读/写C语言的我,决定要啃一下Red...

    Jackeyzhe
  • 【redis6.0.6】深入源码,一探究竟 -- redis服务器开机自启动

    本篇搭配: 【redis6.0.6】redis源码慢慢学,慢慢看 – 第四天:提纲掣领main函数(server)

    看、未来
  • 【阿里】在 nginx 中如何配置负载均衡

    堡垒山上的珀纳里城堡,法加拉斯山,罗马尼亚 (© porojnicu/Getty Images)

    山月
  • nginx 禁止ip直接访问,防止恶意解析

    找到 nginx 的默认配置文件 nginx.conf 编辑文件找到 默认的80 server

    Alone88
  • AFNetworking+Python+Flask+pyOpenSSL构建iOS HTTPS客户端&服务器端

    最后我现有的感觉是, 在HTTP服务器上放一个证书, 在原本的HTTP访问之前客户端先检查证书是否正确

    周希
  • 如何配置Spring Boot Tomcat

    Spring Boot Web应用程序默认包含预配置的嵌入式Web服务器。但在某些情况下,我们要修改默认配置以满足自定义要求。

    乱敲代码
  • 基于Python3的资产处理工具「bufferfly」

    攻防演习/渗透测试资产处理小工具,对攻防演习/渗透测试前的信息搜集到的大批量资产/域名进行存活检测、获取标题头、语料提取、常见Web端口检测等。

    HACK学习

扫码关注云+社区

领取腾讯云代金券