1. 程式人生 > >使用redis進行使用者介面訪問時間次數限制

使用redis進行使用者介面訪問時間次數限制

假設一個使用者(用IP判斷)每分鐘訪問某一個服務介面的次數不能超過10次


import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;


/**
 * 
 * <p>Title:</p>
 */
public class RateLimit {



private static final Logger logger = LogUtil.get();

private static final String RATE_LIMIT = "RATELIMIT";

/** 
     * @Title: allow @Description: 進行流量控制,允許訪問返回true 不允許訪問返回false  
     * @param: @param key 放入redis的key,放入前要在key之前新增字首 字首配置在eds.properties中的 redis.prefix 
     * @param: @param timeOut 超時時間單位秒 
     * @param: @param count 超時時間內允許訪問的次數 
     * @param: @param type 不同型別的資料
     * @param: @return 
     * @param: @throws 
     *             Exception @return: boolean @throws 
     */  
    public static boolean allow(String type,String key, int timeOut, int count) {  
  
//        Boolean useFc = Boolean.valueOf(EdsPropertiesUtil.getInstance().getProperty("flowControl.use"));  
//        // 若不使用流量控制直接返回true  
//        if (!useFc) {  
//            return true;  
//        }  
  
        boolean result = false;  
        Jedis jedis = null;  
        StringBuffer keyBuff = new StringBuffer(RATE_LIMIT);
        keyBuff.append("_").append(type).append(":").append(key);
        key = keyBuff.toString();
        try {  
        jedis = new Jedis(ConfigurationUtil.getRedisHost(), Integer.valueOf(ConfigurationUtil.getRedisPort()));
    if (StringUtils.isNoneEmpty(ConfigurationUtil.getRedisPassWord())) {
    jedis.auth(ConfigurationUtil.getRedisPassWord());
    }
    jedis.connect();
            Long newTimes = null;  
            Long pttl = jedis.pttl(key);  
  
            if (pttl > 0) {  
                newTimes = jedis.incr(key);  
                if (newTimes > count) {  
                    logger.info("key:{},超出{}秒內允許訪問{}次的限制,這是第{}次訪問", new Object[] { key, timeOut, count, newTimes });  
                } else {  
                    result = true;  
                }  
            } else if (pttl == -1 || pttl == -2 || pttl == 0) {  
  
                Transaction tx = jedis.multi();  
                Response<Long> rsp1 = tx.incr(key);  
                tx.expire(key, timeOut);  
                tx.exec();  
                newTimes = rsp1.get();  
                if (newTimes > count) {  
                    logger.info("key:{},{}秒內允許訪問{}次,第{}次訪問", new Object[] { key, timeOut, count, newTimes });  
                } else {  
  
                    result = true;  
                }  
  
            }  
            if (result) {  
                logger.debug("key:{},訪問次數{}", new Object[] { key, newTimes });  
            }  
  
        } catch (Exception e) {  
            logger.error("流量控制發生異常", e);  
            e.printStackTrace();  
            // 當發生異常時 允許訪問  
            result = true;  
        } finally {  
            jedis.close();  
        }  
  
        return result;  
  
    }  
}
ConfigurationUtil 為配置檔案中的值

方法呼叫:

// 限制器,限制在60秒之內最多登入5次

if (RateLimit.allow("RECOMMENDCODE",accountCode, 60, 5)) {
             //處理業務
        }else{
   //返回失敗
       }