分布式限流方案实现

作者: 8e7f75130086 | 来源:发表于2018-07-14 16:45 被阅读95次

分布式限流

一、需求背景:

1、纵横客业务调用口碑接口时(尤其是定时任务调接口提数),常常收到口碑网关返回isv.app-call-limited 超过调用频率限制,
目前仅仅是简单做了一下Thread.sleep(随机数)来实现平滑请求。
2、定时任务作为一个次级业务,当数据库压力过大时(尤其是业务高峰期),理论上应该减小定时任务的流量,为关键业务让路。
目前无法控制定时任务对数据库的压力
3、工作流启动后为多节点分布式数据计算,但是调用口碑为同一API接口,无法通过单机进行限流

二、需求目的

1、通过对调用口碑API接口的相关任务进行限流,来实现平滑调用,并且避免sleep引起的性能损耗
2、通过对数据库操作的代码块进行限流,来实现平滑调用,并且避免sleep引起的性能损耗
3、通过数据库压力的动态反馈,对数据库操作进行动态限流。动态实现错峰运行

三、实现方案

1、使用guava提供工具库里的RateLimiter类(单机限流)
内部采用令牌捅算法实现进行限流
2、redis+lua(分布式限流)
分布式限流最关键的是要将限流服务做成原子化。使用redis+lua实现某时间窗内某个接口的请求数限流

四、接口

     /**
     * 限流
     * @return true:限流阈值内;false:超过限流阈值
     * @see DistributionRatelimiter.DEFAULT_LIMIT
     */
    public boolean limit();
    /**
     * 限流
     * @param limit限流量
     * @see DistributionRatelimiter.DEFAULT_TIMEUNIT
     * @return true:限流阈值内;false:超过限流阈值
     */
    public boolean limit(int limit);
    /**
     * 限流
     * @param limit 限流量
     * @param unit 限流单位
     * @return true:限流阈值内;false:超过限流阈值
     */
    public boolean limit(int limit,TimeUnit unit);
        /**
     * 限流
     * @param method 指定方法限流
     * @param limit限流量
     * @param unit限流单位
     * @returntrue:限流阈值内;false:超过限流阈值
     */
    public boolean limit(String method,int limit,TimeUnit unit);

五、用法

配置

①引入配置文件

<import resource="classpath:bean/summonercloud-ratelimiter.xml" />

②依赖jar包

<dependency>
    <groupId>com.yunzong.summonercloud</groupId>
    <artifactId>summonercloud-ratelimiter</artifactId>
    <version>1.0.1.2374</version>
</dependency>

使用

③bean注入

@Resource
RedisRatelimiter dRatelimiter;

④方法调用

//例如:一分钟限流500
<!--核心代码片段-->
boolean result = dRatelimiter.limit(500, TimeUnit.MINUTES);
if(result) {
    //没有限流,处理业务。。。。
}else {
    //被限流,拒绝服务
}

六、思考

如何动态感知数据库压力并且动态采取限流量措施实现错峰运行?
   需要DBA沟通看看有什么方案。

七、附Lua脚本

--
--lua 下标从 1 开始
-- 限流 key
local key = KEYS[1]
-- 限流大小
local limit = tonumber(ARGV[1])

local MINUTES = "MINUTES"

-- 获取当前流量大小
local curentLimit = tonumber(redis.call('get', key) or "0")
local m = ARGV[2]
if curentLimit + 1 > limit then
    -- 达到限流大小 返回
    return 0;
else
    -- 没有达到阈值 value + 1
    redis.call("INCRBY", key, 1)
    if m == MINUTES then
        redis.call("EXPIRE", key, 120)
    else
        redis.call("EXPIRE", key, 2)
    end
    return curentLimit + 1
end

相关文章

  • 分布式限流方案实现

    分布式限流 一、需求背景: 二、需求目的 三、实现方案 1、使用guava提供工具库里的RateLimiter类(...

  • 分布式限流之Redis+Lua实现

    分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使用redis+lua或者nginx+lua技术进行实现...

  • 分布式限流之Redis+Lua实现

    分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使用redis+lua或者nginx+lua技术进行实现...

  • 分布式限流

    利用Redis实现分布式限流

  • 技术博客

    1. 基于Redis实现分布式应用限流

  • 聊聊高并发系统之限流特技-2

    摘要:上一篇《聊聊高并发系统限流特技-1》讲了限流算法、应用级限流、分布式限流;本篇将介绍接入层限流实现。 接入层...

  • RateLimiter-源码分析

    一、前言 在分布式系统中,实现高可用有三大利器: 限流 降级 熔断我们先对限流来进行一个分析。 二、限流的实现 业...

  • 分布式的东西

    1、分布式总体限流方案 例 100w总流量限流如何在100台分布机做总体限流 2、如何设计秒杀系统,应该关注什么:...

  • Redis+Lua脚本三步实现分布式系统限流

      在分布式系统中,说到限流方案我们一般会使用redis结合限流算法来做,一般的限流算法有令牌桶算法、漏桶算法、固...

  • Redis+Lua实现限流

    分布式限流最关键的是要将限流服务做成原子化,而解决方案可以使使用redis+lua或者nginx+lua技术进行实...

网友评论

    本文标题:分布式限流方案实现

    本文链接:https://www.haomeiwen.com/subject/jbyypftx.html