API安全(三)-流控


1、什么是流控

  所謂流控,就是流量控制,也稱作限流。只放系統能夠處理的請求數量過去。

2、為什么要做流控

  保證系統的可用性,防止大流量把系統壓死。如果系統不可用。其實做什么都沒有意義了。還以用作安全目的,比如可以減慢暴力密碼破解的速率。還可以用來抵御DDOS攻擊。

3、流控為什么要在整個安全機制鏈路的第一關

  因為認證、審計,授權都是需要消耗系統資源的。能夠越早把一些請求拒絕掉,資源的浪費就會越少。就能處理更多的請求。所以流控應該是在整個安全機制的最前面。且就算后面的安全機制做的再好,服務器被大流量壓死了,服務不可用也沒用了。

  

4、流控可以在什么地方做

  4.1、在負載均衡、反向代理上做,一般是針對整個集群來做的。比如說在nginx上,和網關上(zuul)等。

  4.2、在自己的應用中,針對單個應用節點。

  可以的話,在兩端都進行配置。

  nginx上做流控限制:https://www.nginx.com/blog/rate-limiting-nginx/

5、使用Guava做簡單的流量控制

  5.1、導入guava依賴

        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>28.0-jre</version>
        </dependency>

  5.2、編寫過濾器

/**
 * 流控過濾器
 * 繼承OncePerRequestFilter,保證一次請求只執行一次該過濾器
 *
 * @author caofanqi
 * @date 2020/1/20 23:29
 */
@Component
@SuppressWarnings("ALL")
public class RateLimiterFilter extends OncePerRequestFilter {

    /**
     * 限制每秒只允許一個請求
     */
    private RateLimiter rateLimiter = RateLimiter.create(1);


    @Override
    protected void doFilterInternal( HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        if(rateLimiter.tryAcquire()) {
            filterChain.doFilter(request, response);
        }else {
            /*
             * 請求過Http狀態碼返回429
             */
            response.setContentType(MediaType.TEXT_HTML_VALUE);
            response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());
            response.getWriter().write("Too Many Requests");
            response.getWriter().flush();
        }

    }

}

  5.3、啟動服務,訪問http://127.0.0.1:9090/users/1 進行快速發送請求測試

  

  當然在實際的開發中,我們所要面對的流控的場景是非常復雜的,不是簡單的設個數就完了。比如說會根據用戶來限流,可能需要把更多的資源留給vip用戶,那么vip用戶可能是每秒500請求,普通用戶可能是每秒50請求。這樣的話,當大量的請求過來之后,vip用戶能正常使用網站,普通用戶可能會有很多請求就被拒絕掉了。

  Guava的RateLimiter類參考文檔:http://ifeve.com/guava-ratelimiter/

 

源碼路徑:https://github.com/caofanqi/study-security/tree/dev-rate-limiter


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM