多维度访问次数限制策略

类型维度
梯度维度
时间段维度

配置文件:

[
    {
        "seconds": 10,
        "times": 5,
        "type": "user_method",
        "errMsg": ""
    },
    {
        "seconds": 30,
        "times": 15,
        "type": "user_method",
        "errMsg": ""
    },
    {
        "times": 100,
        "type": "user",
        "errMsg": ""
    },
    {
        "times": 200,
        "type": "method",
        "errMsg": ""
    },
    {
        "times": 200,
        "type": "range_time",
        "range_time": "18:00-19:00",
        "errMsg": ""
    },
    {
        "times": 200,
        "type": "range_time",
        "range_time": "19:00-20:00",
        "errMsg": ""
    }
]

实现代码:

public RequestLimit tryRequest(final List<RequestLimit> requestLimitList, final String methodName, final Integer userId) {
    Assert.isTrue(StringUtil.isNotBlank(methodName), "tryRequest param methodName is empty!");
    Assert.isTrue(userId != null && userId > 0, "tryRequest param userId is empty!");
    Object ret = runTask(new Callback() {
        @Override
        public RequestLimit onTask(Jedis jedis) {
            boolean flag = true;
            log.info(String.format("[reqLimit_request] \t methodName, userId\t : %s,%s", methodName, userId));
            for (RequestLimit limit : requestLimitList) {

                Integer seconds = limit.getSeconds();
                Integer times = limit.getTimes();
                String type = limit.getType() ;
                if (flag && "user_method".equals(type)) {
                    flag = limitUserMethod(jedis, seconds, times, methodName, userId);
                } else if (flag && "user".equals(type)) {
                    flag = limitUser(jedis, times, userId);
                } else if (flag && "method".equals(type)) {
                    flag = limitMethod(jedis, times, methodName);
                } else if (flag && "range".equals(type)) {
                    flag = limitRangeTime(jedis, limit, userId);
                }
                if (!flag) {
                    return limit;
                }
            }
            log.info(String.format("[reqLimit_pass] \t seconds, methodName, userId :\t %s,%s", methodName, userId));
            return null;
        }
    });

    return ret == null ? null : (RequestLimit) ret;
}

private boolean limitRangeTime(Jedis jedis, RequestLimit limit, Integer userId) {
    long nowTime = System.currentTimeMillis();
    long rangeStartTime = limit.getRangeStartTime();
    long rangeEndTime = limit.getRangeEndTime();
    Integer times = limit.getTimes();
    PreconditionsUtil.checkArguments(times != null, "400", "RequestLimit times is null");

    if (rangeStartTime <= nowTime && nowTime < rangeEndTime) {
        long seconds = rangeEndTime - nowTime;
        log.info(String.format("[reqLimit_error:USER_RANGE_TIME] \t range_time, times, seconds, userId :\t %s,%s,%s,%s",
                limit.getRangeTime(), times, seconds, userId));
        final String key = String.format(USER_RANGE_TIME_REQUEST_LIMIT, rangeEndTime, userId);
        String mistr = jedis.get(key);
        if (mistr == null || Integer.parseInt(mistr) == 0) {
            jedis.incr(key);
            jedis.expire(key, (int) seconds);
        } else if (jedis.incr(key) >= times) {
            log.error(String.format("[reqLimit_error:USER_RANGE_TIME] \t times, seconds, userId :\t %s,%s,%s",
                    jedis.get(key), seconds, userId));
            return false;
        }
    }
    return true;
}

private boolean limitUser(Jedis jedis, Integer times, Integer userId) {
    long dayEndTime = DateUtil.getDayEndTime();
    final String key = String.format(USER_REQUEST_LIMIT, dayEndTime, userId);

    long seconds = dayEndTime - System.currentTimeMillis();
    String mistr = jedis.get(key);
    log.info(String.format("[reqLimit_error:USER] \t times, seconds, userId :\t %s,%s,%s",
             times, seconds, userId));
    if (mistr == null || Integer.parseInt(mistr) == 0) {
        jedis.incr(key);
        jedis.expire(key, (int) seconds);
    } else if (jedis.incr(key) >= times) {
        log.error(String.format("[reqLimit_error:USER] \t times, seconds, userId :\t %s,%s,%s",
                jedis.get(key), seconds, userId));
        return false;
    }
    return true;
}

private boolean limitMethod(Jedis jedis, Integer times, String methodName) {
    long dayEndTime = DateUtil.getDayEndTime();
    final String key = String.format(METHOD_REQUEST_LIMIT, dayEndTime, methodName);

    long seconds = dayEndTime - System.currentTimeMillis();

    log.info(String.format("[reqLimit_error:METHOD] \t times, seconds, methodName :\t %s,%s,%s",
            times, seconds, methodName));
    String mistr = jedis.get(key);
    if (mistr == null || Integer.parseInt(mistr) == 0) {
        jedis.incr(key);
        jedis.expire(key, (int) seconds);
    } else if (jedis.incr(key) >= times) {
        log.error(String.format("[RequireRequestLimit_over:METHOD] \t times, seconds, methodName :\t",
                jedis.get(key), seconds, methodName));
        return false;
    }
    return true;
}

private boolean limitUserMethod(Jedis jedis, Integer seconds, Integer times, String methodName, Integer userId) {
    final String key = String.format(METHOD_USER_REQUEST_LIMIT, seconds, methodName, userId);

    String mistr = jedis.get(key);

    log.info(String.format("[reqLimit_error:METHOD] \t times, seconds, methodName, userId :\t %s,%s,%s,%s",
            times, seconds, methodName, userId));
    if (mistr == null || Integer.parseInt(mistr) == 0) {
        jedis.incr(key);
        jedis.expire(key, seconds);
    } else if (jedis.incr(key) >= times) {
        log.error(String.format("[RequireRequestLimit_over:USER_METHOD] \t times, seconds, methodName, userId :\t",
                jedis.get(key), seconds, methodName, userId));
        return false;
    }
    return true;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值