天天看点

zuul网关_SpringCloud学习笔记——旧服务网关Zuul服务限流服务限流

zuul网关_SpringCloud学习笔记——旧服务网关Zuul服务限流服务限流

服务限流

服务网关的一个重要功能即服务限流。在Zuul中虽然可以通过前置类型过滤器对有效请求和无效请求(参数有效性,合法性)进行校验,将无效请求隔离在服务网关之外(返回错误提示信息、异常信息)。但有的时候某一个时间点内突发有效请求量很大,超过了系统可承受的范围,此时可以依靠服务限流算法,限制该时间点内通过的请求数,保证系统可用,避免出现服务雪崩效应。

此时可以通过Spring Cloud提供的Resilience4j限速器(RateLimiter)进行限速,也可以使用spring-cloud-zuul-ratelimit包。

项目依赖

<dependency>            <groupId>io.github.resilience4jgroupId>            <artifactId>resilience4j-spring-boot2artifactId>            <version>0.13.2version>        dependency>                <dependency>            <groupId>com.marcosbarbero.cloudgroupId>            <artifactId>spring-cloud-zuul-ratelimitartifactId>            <version>2.2.2.RELEASEversion>        dependency>
           

使用Resilience4j限流

限流配置

#resilience4j限流配置resilience4j.ratelimiter.limiters.user-service.limit-for-period=3resilience4j.ratelimiter.limiters.user-service.limit-refresh-period-in-millis=5000resilience4j.ratelimiter.limiters.user-service.timeout-in-millis=10
           

上述配置中,resilience4j.ratelimiter.limiters.user-service.limit-for-period配置时间戳内的请求数(默认为50),limit-refresh-period-in-millis配置时间戳(单位毫秒,默认500),timeout-in-millis配置超时时间。user-service可以替换为其他有意义的名称。

限流过滤器

@Componentpublic class Resilience4jRateLimiterFilter extends ZuulFilter {    //Resilience4j限速器注册机    @Autowired    private RateLimiterRegistry rateLimiterRegistry;    /**     * 返回过滤器类型     * @return 前置类型过滤器     */    @Override    public String filterType() {        return FilterConstants.PRE_TYPE;    }    /**     * 返回过滤器执行顺序      * @return     */    @Override    public int filterOrder() {        return FilterConstants.PRE_DECORATION_FILTER_ORDER+5;    }    /**     * 返回过滤器是否执行拦截操作     * @return 请求路径是否为/user/开头     */    @Override    public boolean shouldFilter() {        RequestContext requestContext=RequestContext.getCurrentContext();        String uri=requestContext.getRequest().getRequestURI();        return uri.startsWith("/user/");    }    /**     * 过滤器具体执行业务逻辑     * @return     * @throws ZuulException     */    @Override    public Object run() throws ZuulException {        //获取Resilience4j限速器(key与配置文件的Key名称一致)        RateLimiter rateLimiter=rateLimiterRegistry.rateLimiter("user-service");        //限速器执行逻辑        Callable callResult=()->new ResultMessage(true,"执行成功");        //绑定限速器        Callable callResult2=RateLimiter.decorateCallable(rateLimiter,callResult);        //尝试获取执行结果        Try resultMessageTry=Try.of(()->callResult2.call()).recover(ex->new ResultMessage(false,"超出限定流量,执行降级操作"));        ResultMessage resultMessage=resultMessageTry.get();      //执行结果返回true,说明在限流范围内,限流操作成功,继续执行后续的自定义过滤器        if(resultMessage.isSuccess())        {            return null;        }        //超过限流范围处理        RequestContext requestContext=RequestContext.getCurrentContext();        requestContext.setSendZuulResponse(false);//不在路由到下一个执行顺序的过滤器,直接返回失败        requestContext.setResponseStatusCode(HttpStatus.TOO_MANY_REQUESTS.value());//设置响应状态码(值为429)        requestContext.getResponse().setContentType(MediaType.APPLICATION_JSON_VALUE);//设置响应类型(APPLICATION_JSON_UTF8_VALUE已废弃)        ObjectMapper responseMapper=new ObjectMapper();        String responseBody=null;        try {            responseBody=responseMapper.writeValueAsString(resultMessage);//将执行结果转换为字符串并输出        }     catch (Exception e)     {         e.printStackTrace();     }        requestContext.setResponseBody(responseBody);        return null;    }}
           

在开发Zuul过滤器的过程中,需要熟悉Zuul过滤器类型及Zuul内置过滤器执行顺序。本例中,限流过滤器应该在过滤有效请求(请求参数有效)后执行,故过滤器执行顺序为前置(pre)过滤器PreDecorationFilter后路由(route)过滤器前(PreDecorationFilter用于处理请求上下文,SimpleHostRoutingFilter用于具体的URL请求转发)。

zuul网关_SpringCloud学习笔记——旧服务网关Zuul服务限流服务限流

我们将Resilience4jRateLimiterFilter(Resilience4j限速过滤器)声明为组件(@Component),在入口程序中被扫描发现并装配;注入限速注册机(RateLimiterRegistry),通过限速注册机获取具体的Resilience4j限速器实例(rateLimiterRegistry.rateLimiter(key));通过RateLimiter.decorateCallable方法(参数为Resilience4j实例,限速器业务逻辑);在尝试获取执行结果的过程中发生异常(限流操作超出限制范围),通过recover方法实现服务降级相关操作(返回缓存结果、服务降级信息、异常),提供更好的用户体验;未超过服务限流范围执行后续的过滤器操作,超过服务限流范围则设置响应信息给服务调用方展现。

Spring-cloud-zuul-ratelimit限流

为了防止微服务系统中的服务调用接口被恶意频繁请求调用,需要在服务网关层进行服务限流对服务调用接口安全性进行保护。使用spring-cloud-zuul-ratelimit可以在Zuul的基础上实现服务网关限流相关功能。

限流方式

限流方式 限流描述
Authenticated User(认证用户) 使用已经认证的用户名或'anonymous'
Request Origin(原始请求) 使用用户的原始请求
URL 使用上游请求的地址
Global configuration per service(全局配置) 针对每个服务的全局配置,无需指定限流方式

配置详解

#spring-cloud-zuul-ratelimit配置(全局配置)#是否开启限速配置(boolean,默认false)zuul.ratelimit.enabled=true #使用Redis缓存对应的度量数据zuul.ratelimit.repository=redis#是否开启代理服务(boolean,默认false)zuul.ratelimit.behind-proxy=true#是否添加响应报头(boolean,默认false)zuul.ratelimit.add-response-header=true#每个刷新时间窗口对应的请求数量限制zuul.ratelimit.default-policy.limit=10#每个刷新时间窗口对应的请求时间限制zuul.ratelimit.default-policy.quota=1000#刷新时间窗口时间(默认60,单位秒)zuul.ratelimit.default-policy.refresh-interval=60#全局限流方式(可选,user,origin,url)zuul.ratelimit.default-policy.type=user#spring-cloud-zuul-ratelimit配置(服务实例配置)#限制用户微服务实例(user-service)刷新时间窗口对应的请求数量限制zuul.ratelimit.user-service.limit=5#限制用户微服务实例(user-service)刷新时间窗口对应的请求时间限制zuul.ratelimit.user-service.quota=100#限制用户微服务实例(user-service)限流方式zuul.ratelimit.user-service.type=origin
           

继续阅读