1. 程式人生 > 其它 >多維度訪問次數限制策略

多維度訪問次數限制策略

技術標籤:技能

型別維度
梯度維度
時間段維度

配置檔案:

[
    {
        "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;
}