首頁>技術>

一、問題描述

某個系統的登入介面在被刷。現要建立一個防刷/限流機制,根據登入 IP,30 分鐘之內,只能發起 30 次登入請求。如果超過該限制,則整個 IP 限制登入請求 30 分鐘。

二、設計思路

這道題主要是設計兩個 Map:

1、第一個 Map,記錄每個 IP 及其登入的時間。題目要求,30 分鐘之內只能登入 30 次,所以 Map 的 key 為 IP,value 可以設計一個佇列,佇列長度 30,佇列元素為每次的登入時間。

2、第二個 Map,記錄禁止登入的 IP 及禁止開始時間。Map 的 key 為 IP,value 為時間。

三、限流器實現程式碼
import java.time.LocalDateTime;import java.util.HashMap;import java.util.LinkedList;public class LimitCacheTool {	private static volatile LimitCacheTool instance;    // 記錄登入的ip地址及每次登入時間    private static HashMap<String, LinkedList<LocalDateTime>> loginMap = new HashMap<>();    // 記錄禁止登入的ip地址及禁止開始時間    private static HashMap<String, LocalDateTime> forbiddenMap = new HashMap<>();    // 構造器私有化,不能在類的外部隨意建立物件    private LimitCacheTool() {    }    // 提供一個全域性的訪問點來獲得這個"唯一"的物件    public static LimitCacheTool getInstance() {        if (instance == null) {            synchronized (LimitCacheTool.class) {                if (instance == null) {                    instance = new LimitCacheTool();                }            }        }        return instance;    }    public static HashMap<String, LinkedList<LocalDateTime>> getLoginMap() {        return loginMap;    }    public static HashMap<String, LocalDateTime> getForbiddenMap() {        return forbiddenMap;    }	}
四、限流實現邏輯
/**	 * @author:JackRen	 * @Description:防刷/限流機制	 * @date:2021年2月26日上午10:35:18	 * @param ip	 */	public void doLimitLogin(String ip) {		String result = "";		LimitCacheTool limitCache = LimitCacheTool.getInstance();        LinkedList<LocalDateTime> queue = null;        // 先判斷ip地址是否禁止登入        LocalDateTime forbiddenTime = limitCache.getForbiddenMap().get(ip);        if (forbiddenTime != null) {            Long after = ChronoUnit.MINUTES.between(forbiddenTime, LocalDateTime.now());            if (after <= 30) {                result = "當前時間=" + LocalDateTime.now() + " 上次禁止登入時間= " + forbiddenTime + " 距上次被禁時間沒有超過30分鐘";                setRespAttr("msg", result);                return;            } else {                limitCache.getForbiddenMap().clear();            }        }        // 如果是首次登入,則建立佇列        if (limitCache.getLoginMap().get(ip) == null) {            queue = new LinkedList<>();        } else {            queue = limitCache.getLoginMap().get(ip);        }        // 登入次數達到登入次數上限        if (queue.size() == 30) {            // 當前時間和佇列中最早的登入時間比較 是否小於30分鐘            LocalDateTime now = LocalDateTime.now();            LocalDateTime firstLoginTime = queue.poll();            Long duration = ChronoUnit.MINUTES.between(firstLoginTime, now);            if (duration <= 30) {                result = "30分鐘內登入超過30次,不允許登入,30分鐘後再登入";                // 禁止該IP登入                limitCache.getLoginMap().clear();                limitCache.getForbiddenMap().put(ip, now);                setRespAttr("msg", result);                return;            }        }        queue.offer(LocalDateTime.now());        limitCache.getLoginMap().put(ip, queue);        result = ip + " 登入時間=" + queue.getLast() + "  佇列長度=" + queue.size();        setRespAttr("msg", result);        return;	}

5
最新評論
  • BSA-TRITC(10mg/ml) TRITC-BSA 牛血清白蛋白改性標記羅丹明
  • JavaScript獲取日期方法