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類參考文檔: