Soul 网关提供了限流插件,方便用户控制指定时间段内经过网关的请求数量。
什么是“限流”?
火锅店一般都有最大的容客量,大桌小桌的席位数是固定的。在就餐高峰期时,大量的食客会蜂拥而至,一般火锅店的员工是根据座位数分配的,如果不限制进入火锅店的人流,员工会忙不过来,食客的体验也会变差。在这里限制座位数就是一种限流的手段。而取到号牌并被叫到号的顾客才能入座就餐,这跟令牌桶
后端架构中的限流一般分为两种,对外主要针对 DDOS攻击以及爬虫防范,对内主要控制热点公共服务调用的均匀分配。
Soul 是如何做限流的?
首先我们来看看 soul-plugin-ratelimiter 的文件目录结构:
└── src
├── main
│ ├── java
│ │ └── org
│ │ └── dromara
│ │ └── soul
│ │ └── plugin
│ │ └── ratelimiter
│ │ ├── RateLimiterPlugin.java AbstractSoulPlugin 实现类,核心函数是 doExecute,
│ │ ├── config
│ │ │ └── RateLimiterConfig.java ratelimiter 相关配置项
│ │ ├── executor
│ │ │ └── RedisRateLimiter.java 基于 redis 的令牌桶算法实现,核心函数是 isAllowed
│ │ ├── handler
│ │ │ └── RateLimiterPluginDataHandler.java 从插件配置读取数据的handler
│ │ └── response
│ │ └── RateLimiterResponse.java ratelimiter response 类
│ └── resources
│ └── META-INF
│ └── scripts
│ ├── concurrent_request_rate_limiter.lua 并发 ratelimiter lua脚本
│ └── request_rate_limiter.lua ratelimiter lua脚本
└── test
首先我们需要启动 redis-server
然后在 admin 中配置 ratelimiter 插件,首先在插件管理中开启 ratelimiter,再配置 ratelimiter 的 selecter 和 rule:
配置完成后使用postman模拟不间断的 200 次请求:
在执行完 10 次后的 第11次,ratelimiter 阻断了我们的请求,因为令牌桶中的令牌已经被消耗光了(capacity 为 10),而填充速率(rate)为 5,意味着用户每秒最多请求 5次 后就被限流。
下图是令牌桶算法的分配流程,其实跟火锅店分配排队号牌是差不多的原理:
总结
ratelimiter 可以帮助我们在网关层过滤掉不需要或者异常的请求而避免消耗后端服务的资源,这也是我认为网关在软件架构中的重要职能之一,Soul 使用 redis 做令牌桶算法,明天的计划是深入剖析 通过 lua 脚本实现令牌桶算法的原理。