首先要保證你的服務是可用的,其中一個重要的手段就是流控。就是流量控制。比如我的系統每秒只能處理500個請求,那么多余的請求就拒絕掉。這樣我的系統不會被壓死
實際的開發中,所要面對的流控場景實際是非常復雜的,在負載均衡上做,反向代理上做,或者自己寫代碼去做也是可以的。。
負載均衡和反向代理一般是針對集群的。
為什么要做流控:
1.保證系統的可用性,不要被大流量把系統壓死,如果你的服務不可用,做什么都沒有意義了。
2.流控一定要做在認證審計授權這些安全機制的前面。因為你的認證審計授權都是要消耗系統資源的,能越早把一些請求拒絕掉,資源的浪費就會越少。越能處理更多的請求。所以流控應該是在整個安全機制的最前面。
用guava來做個示例。先查一下最新的版本
粘貼到項目的pom.xml內
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.0-jre</version>
</dependency>
創建過濾器
所有的請求都要做流量的統計。我們在一個過濾器里面做這個事
繼承OncePerRequestFilter,這是Spring框架提供的Filter。繼承這個,可以保證你的過濾器的邏輯在一個請求里面,永遠只會被執行一次。因為有些情況下可能在一個請求里面可能會多次執行這個過濾器。這樣繼承了OncePerRequestFilter。就會保證你的過濾器邏輯不會被多次執行。
首先把它聲明稱一個Spring 的Component組件。
進入OncePerRequestFilter這個類里
OncePerRequestFilter繼承自GenericFilterBean。再進入GenericFilterBean
GenericFilterBean繼承了Filter。再進去Filter
再進Filter。這是javax.servlet包下的一個接口。
任何繼承了Filter這個接口的類。比如說我們寫的這個類RateLimitFilter。SpringBoot會自動的把它加到Web應用的過濾器鏈上,只要把它聲明稱@Component 其他的不用配置
create是一個靜態方法,它會幫你創建一個流控的控制器。
默認情況下就是每秒的請求數為1,1秒一個請求。
它還包含了其他參數,可以指定時間單位。不指定的話默認是就是1秒。
然后在過濾器里面做一個判斷就可以了。在http請求里面,當一個請求過多 有一個固定的狀態碼429,當請求大道了限流,就會設置請求的狀態碼為429
把錯誤信息輸出,然后刷一下write。最后返回。
以上就是一個最簡單的限流器。
@Component public class RateLimitFilter extends OncePerRequestFilter { //create是一個靜態方法,它會幫你創建一流控的控制器 private RateLimiter rateLimit= RateLimiter.create(1); @Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { if(rateLimit.tryAcquire()){ filterChain.doFilter(request,response); }else{ response.setStatus(HttpStatus.TOO_MANY_REQUESTS.value());//403錯誤 response.getWriter().write("too many request!!!!"); response.getWriter().flush(); return; } } }
測試
如果很快的去刷新頁面
返回的狀態碼就是429