结合SpringMvc进行简单限流

这里用google的Guava包来实现(注意是单机下的),当然我们也可以自己实现限流

具体限流种类以及基本原理,会有单独的文章讲


首先引入guava依赖

<dependency>
    <groupId>com.google.guava</groupId>
    <artifactId>guava</artifactId>
    <version>21.0</version>
</dependency>

写一个SpringMVC的拦截器
SmoothBurstyInterceptor.java

import com.google.common.util.concurrent.RateLimiter;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.concurrent.TimeUnit;

public class SmoothBurstyInterceptor extends HandlerInterceptorAdapter {

    public enum LimitType {
        DROP,//丢弃
        WAIT //等待
    }

    /**
     * 限流器
     */
    private RateLimiter limiter;
    /**
     * 限流方式
     */
    private LimitType limitType = LimitType.DROP;

    public SmoothBurstyInterceptor() {
        this.limiter = RateLimiter.create(10);
    }

    /**
     * @param tps       限流量 (每秒处理量)
     * @param limitType 限流类型:等待/丢弃(达到限流量)
     */
    public SmoothBurstyInterceptor(int tps, SmoothBurstyInterceptor.LimitType limitType) {
        this.limiter = RateLimiter.create(tps);
        this.limitType = limitType;
    }
    /**
     * @param permitsPerSecond  每秒新增的令牌数
     * @param limitType 限流类型:等待/丢弃(达到限流量)
     */
    public SmoothBurstyInterceptor(double permitsPerSecond, SmoothBurstyInterceptor.LimitType limitType) {
        this.limiter = RateLimiter.create(permitsPerSecond, 1000, TimeUnit.MILLISECONDS);
        this.limitType = limitType;
    }


    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        if (limitType.equals(LimitType.DROP)) {
            if (limiter.tryAcquire()) {
                return super.preHandle(request, response, handler);
            }
        } else {
            limiter.acquire();
            return super.preHandle(request, response, handler);
        }
        throw new Exception("网络异常!");//达到限流后,往页面提示的错误信息。
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        super.postHandle(request, response, handler, modelAndView);
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        super.afterCompletion(request, response, handler, ex);
    }

    public RateLimiter getLimiter() {
        return limiter;
    }

    public void setLimiter(RateLimiter limiter) {
        this.limiter = limiter;
    }
}

对拦截器进行配置

WebConfig.java

@Component
public class WebConfig extends WebMvcConfigurerAdapter {
    
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        // 多个拦截器组成一个拦截器链
        registry.addInterceptor(new SmoothBurstyInterceptor(100, SmoothBurstyInterceptor.LimitType.DROP)).addPathPatterns("/**");
        //限流可配置为SmoothBurstyInterceptor.LimitType.DROP丢弃请求或者SmoothBurstyInterceptor.LimitType.WAIT等待,100为每秒的速率
        super.addInterceptors(registry);
    }

}

完成

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 在系统架构设计当中,限流是一个不得不说的话题,因为他太不起眼,但是也太重要了。这点有些像古代镇守边陲的将士,据守隘...
    Java大生阅读 4,168评论 0 0
  • 在系统架构设计当中,限流是一个不得不说的话题,因为他太不起眼,但是也太重要了。这点有些像古代镇守边陲的将士,据守隘...
    java菜阅读 2,761评论 0 4
  • 占小狼[//www.greatytc.com/users/90ab66c248e6/latest_art...
    美团Java阅读 19,017评论 4 111
  • 今天在看某一公众号时,看到有在推另外一个公号,然后就关注获得了一本叫做《普通人成长必备的高效能手册》,是本电子书,...
    RexsonXie阅读 5,302评论 0 0
  • Python的基础语法 一、注释 程序中的说明文字,没有任何程序功能,不会被执行单行注释:就是在说明文字前加 #...
    y_j杨健阅读 1,332评论 0 0