限流RateLimiter在Web應用中的使用
阿新 • • 發佈:2019-01-09
Google的Guava是JDK補充的一個神器,值得好好學習。
一般Web系統的訪問限制都可以用容器本身來實現,比如tomcat就可以在connector上面配置connection數目的限制,servlet thread限制。
有時候系統複雜後希望對不同服務提供不同的RateLimiter,例如對資料庫操作要求比較大的速率小些,在記憶體可以處理的速率大寫,還有可能對叢集提供rate limiter服務。
如何限速是一個公共話題,相關的演算法和實現都有一大堆,有興趣可以看看Calvin的springside4 wiki關於這個章節的描述,寫的非常棒。
這裡記錄下實踐過程中系統如何使用RateLimiter來限制所有spring訪問的訪問速率,簡單版,沒有注入化ratelimiter需要的輸入引數。
1. 定義Filter
public class RateLimiterFilter implements Filter { private static Logger logger = Logger.getLogger(RateLimiterFilter.class); private RateLimiter limiter = null; public void init(FilterConfig config) throws ServletException { limiter = RateLimiter.create(100); //100 request per second } public void destroy() { } public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { HttpServletRequest req = (HttpServletRequest) request; HttpServletResponse res = (HttpServletResponse) response; if(limiter.tryAcquire()) { if(logger.isTraceEnabled()){ logger.trace("get access: "); } chain.doFilter(request, response) } else { logger.info("system limitation reached!"); req.getRequestDispatcher("/WEB-INF/jsp/error/429.jsp").forward(req,res); } } }
2. 修改Web.xml
<filter> <filter-name>ratelimiter</filter-name> <filter-class>RateLimiterFilter</filter-class> </filter> <filter-mapping> <filter-name>ratelimiter</filter-name> <servlet-name>springmvc</servlet-name> </filter-mapping>
3. Maven中引入RateLimiter包
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>18.0</version>
</dependency>