当前位置: 首页 > news >正文

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制

  1. 配置

1.1参数

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
1.2 Params.Quota

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
1.3Params.Override

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
1.4Params.QuotaAlgorithm

速率限制的算法:

Fixed Window 算法每个时间间隔对应一个计数器,每当有请求到来,如果此时计数器未达到配额的限定值,则计数器加 1,否则拒绝服务。当进入下一个时间间隔时,计数器失效被重置。该算法的缺点在于不能保证在任意的时间间隔内,速率都被限制在配额以下。即如果请求集中在计数器失效的时间点附近,则在该时间点附近的时间间隔内,速率最大能达到配额的两倍。

Rolling Window 算法通过对上一个时间间隔请求数和当前时间间隔已处理的请求数进行加权,实现了对任意时间间隔的速率的估算。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
图片来自

https://blog.cloudflare.com/counting-things-a-lot-of-different-things/

如上图所示,在上一分钟内处理了 42 个请求,当前这一分钟已经过去了 15 秒,处理了 18 个请求,则当前这一分钟的速率可以估算为:

rate = 42 ((60-15)/60) + 18 = 42 0.75 + 18 = 49.5

如果使用 memquota adapter,默认使用亚秒级分辨率的 rolling window 实现速率限制。

如果使用 redisquota adapter,可以配置使用 Rolling Window 算法或者 Fixed Window 算法。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
1.5例子

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
上面的 redisquota handler 定义了三种不同的速率限制模式:

如果没有 override 能够匹配,默认每秒限制 500 次请求;

如果请求的 destination 是 reviews,每秒限制 1 次请求;

如果请求的 destination 是 productpage,每秒限制 2 次请求。

  1. 代码分析

2.1Mixer Server 启动时注册 Check 接口的流程

首先从 Mixer Server 的启动入口 main() 函数看起,在 istio/mixer/cmd/mixs/main.go 中:

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 main() 函数中调用了 GetRootCmd() 方法,获取 cobra 命令树的根节点。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 GetRootCmd() 方法中添加了 serverCmd() 命令。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 serverCmd() 中定义了,当我们执行 mixs server 命令时,会调用 runServer() 函数,将 mixer 作为一个 gRPC server 启动。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 runServer() 中,调用了 server.New() 方法,初始化了一个具备全部功能的 Mixer server,可以开始接收流量。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 server.New() 方法中,调用了 newServer() 函数。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 newServer() 函数中,通过调用 grpc.NewServer() 方法,创建了一个 gRPC server,但是尚未注册服务,而且未启动去接收请求。然后调用了 RegisterMixerServer() 函数注册 Mixer 服务。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 RegisterMixerServer() 函数中,调用了上面创建的 gRPC server 的 RegisterService() 方法在该 gRPC server 中注册 Mixer 服务。该方法的参数 _Mixer_serviceDesc 是对 Mixer 服务的描述。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在对 Mixer 服务的描述中可以看出,该服务提供了两个接口,分别是 Check 和 Report。限流功能调用的是 Check 接口。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在处理 Check 请求的 handler 中,定义了该接口的 RPC 方法全称,并且调用了 MixerServer 接口提供的 Check() 方法。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
MixerServer 接口定义了 Mixer 服务提供的 API。Check接口在执行对服务的调用之前,预先对一些条件进行检查,并分配配额。

2.2运行时 Mixer 处理 Check 接口调用的流程

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
如上图所示,在 istio/mixer/pkg/api/grpcServer.go 中实现了 MixerServer 接口。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 MixerServer 接口的 Check() 方法的实现中,调用了 check() 方法。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 check() 方法中调用了 Dispatcher 接口的 Quota() 方法。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
如上图所示是 Dispatcher 接口的定义,Quota() 方法将请求分发到与 Quota API 相关的 adapter。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
上图所示是 Quota() 方法在运行时的实现,在实现时调用了 dispatch() 方法。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 dispatch() 方法中,通过 session 的 variety 字段区分 preprocess、check、report 或 quota 几种操作类型。如果是 quota 操作,首先匹配和 quota 的名称对应的 instance,然后调用 dispatchToHandler() 方法对匹配到的 instance 进行分发。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 dispatchTohandler() 方法中,调用了 ScheduleWork() 方法,注册 invokeHandler() 方法,使其在某个时间点被调用。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 invokeHandler() 方法中,通过调用 DispatchQuota() 方法,将 instace 分发到 Redis Quota adapter。

2.3Mixer Server启动时注册DispatchQuota() 函数流程

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 Mixer Server 的启动入口 main() 函数中,调用 supportedTemplates() 函数传入了支持的模板。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
supportedTemplates() 函数返回 generatedTmplRepo.SupportedTmplInfo。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
在 generatedTmplRepo 包中,将 SupportedTmplInfo 的 DispatchQuota 字段定义为上述函数,在该函数中调用了 Redis Quota Adatper 的 HandleQuota() 方法。

2.4Redis Quota Adapter 的实现

2.4.1结构定义

首先定义 handler 结构如下:

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
其中 client 字段是一个 Redis client,用于连接存放 quota 信息的 Redis 数据库;limits 字段用于存放用户配置的限制;dimensionHash 字段用于存放用户定义的 override 的 dimension 的 hash;scripts 字段用于存放两种限流算法的 Lua 脚本供 Redis 使用;getTime() 用于获取当前时间。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
builder 结构用于构建 handler,包含 quotaTypes 和 adapterConfig 两个字段。adapterConfig 字段用于存放构建 handler 时需要的参数。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
Params 结构定义如上,Quotas 字段是用户定义的限制,RedisServerUrl 字段存放 Redis server 的地址,ConnectionPoolSize 字段存放到 Redis 的最大的 idle 连接数。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
Params_Quota 结构定义如上。Name 字段是 quota 的名称;MaxAmount 是分配 quota 数量的上限;ValidDuration 是分配的 quota 有效的时间;BucketDuration 字段仅在 RollingWindow 算法中使用,是窗口滑动的时间间隔;RateLimitAlgorithm 字段是限流算法的名称,默认值是 FIXED_WINDOW;Overrides 字段定义了在某些条件下对默认规则的覆盖。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
Params_Override 结构定义如上。Dimensions 字段定义了该 override 适用的条件,MaxAmount 定义了该 override 下分配 quota 数量的上限。

2.4.2启动时的配置方法

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
Validate() 方法对 builder 的参数进行校验,并检查 Redis 是否能连通,以及 Lua 脚本是否被导入 Redis。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
Build() 方法通过 builder 构建 handler。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
getDimensionHash() 方法计算 dimension 的 hash,在 Build() 方法中被调用,用于构建 handler。

2.4.3运行时方法

在 2.3 节中提到,Redis Quota Adapter 运行时的入口是 HandleQuota() 方法,该方法可以分为 3 个部分。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
首先是调用 getKeyAndQuotaAmount() 方法,获取该 instance 适用的 key 和 maxAmount。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
getKeyAndQuotaAmount() 方法实现如上。如果该 instance 没有任何 override 能够匹配,那么 key 为 quota 的名称,maxAmount 为该 quota 默认的 maxAmount。如果匹配到了某个 override,那么 key 为 quota 的名称加上该 override 的 dimension 的 hash,maxAmount 为该 override 的 maxAmount。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
第二步是调用 Redis 中的限流算法的 Lua 脚本,根据配置信息和参数信息,获取运行结果。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
然后调用 getAllocatedTokenFromResult() 函数,将 Redis 的返回结果转换成分配的 token 数和有效时间,返回最终结果。

idou老师教你学istio30:Mixer Redis Quota Adapter 实现和机制
getAllocatedTokenFromResult() 函数定义如上,Redis 的返回结果应该有两个值,第一个值为分配的 token 数,第二个值为 token 有效的时间。

相关服务请访问:https://support.huaweicloud.com/cce/index.html?utm_content=cce_helpcenter_2019

转载于:https://blog.51cto.com/14051317/2374361

相关文章:

  • Anaconda 和 JetBrains 联手推出 'Anaconda的PyCharm'
  • 苹果、三星、华为们进场,睡眠产业的百家争鸣
  • Redis主从数据库同步
  • 前嗅ForeSpider脚本教程-链接抽取:链接在源码的js变量里写脚本
  • VS2017运行旧版本下的C程序工程
  • 2019年web前端前景分析
  • Learning OSG programing---Multi Camera in one window 在单窗口中创建多相机
  • 脚本检测Kafka和Zookeeper
  • 线程池参数原理及应用
  • 说说我心中的Linux系统
  • 第七周java学习总结
  • python集合和字典
  • Python操作json对象
  • P2571 [SCOI2010]传送带
  • CentOS7.2重置root密码的处理方法
  • 【5+】跨webview多页面 触发事件(二)
  • Fastjson的基本使用方法大全
  • JavaScript类型识别
  • JavaScript实现分页效果
  • Spring框架之我见(三)——IOC、AOP
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • webpack4 一点通
  • 从0到1:PostCSS 插件开发最佳实践
  • 大数据与云计算学习:数据分析(二)
  • 电商搜索引擎的架构设计和性能优化
  • 精益 React 学习指南 (Lean React)- 1.5 React 与 DOM
  • 配置 PM2 实现代码自动发布
  • 什么是Javascript函数节流?
  • Linux权限管理(week1_day5)--技术流ken
  • 回归生活:清理微信公众号
  • 如何正确理解,内页权重高于首页?
  • 通过调用文摘列表API获取文摘
  • ​iOS安全加固方法及实现
  • (06)金属布线——为半导体注入生命的连接
  • (2)MFC+openGL单文档框架glFrame
  • (2)关于RabbitMq 的 Topic Exchange 主题交换机
  • (附源码)php投票系统 毕业设计 121500
  • (黑马出品_高级篇_01)SpringCloud+RabbitMQ+Docker+Redis+搜索+分布式
  • (蓝桥杯每日一题)love
  • (未解决)macOS matplotlib 中文是方框
  • (最全解法)输入一个整数,输出该数二进制表示中1的个数。
  • .mkp勒索病毒解密方法|勒索病毒解决|勒索病毒恢复|数据库修复
  • .NET BackgroundWorker
  • .net core 6 使用注解自动注入实例,无需构造注入 autowrite4net
  • .NET Framework杂记
  • .Net MVC4 上传大文件,并保存表单
  • ??myeclipse+tomcat
  • ?php echo ?,?php echo Hello world!;?
  • @RequestMapping用法详解
  • [《百万宝贝》观后]To be or not to be?
  • [<死锁专题>]
  • [Android]竖直滑动选择器WheelView的实现
  • [BJDCTF2020]The mystery of ip
  • [C#]获取指定文件夹下的所有文件名(递归)
  • [C#]无法获取源 https://api.nuge t.org/v3-index存储签名信息解决方法