多維度訪問次數限制策略
阿新 • • 發佈:2021-01-26
技術標籤:技能
型別維度
梯度維度
時間段維度
配置檔案:
[ { "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; }