1. 程式人生 > >限流RateLimiter在Web應用中的使用

限流RateLimiter在Web應用中的使用

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>