微服务开发中有时需要对API做限流保护,防止网络攻击,比如做一个短信验证码API,限制客户端的请求速率能在一定程度上抵御短信轰炸攻击,降低损失。微服务网关是每个请求的必经入口,非常适合做一些API限流、认证之类的操作,本文介绍Zuul如何进行限流操作,对zuul不了解的可以参考我这篇文章:SpringCloud组件之Zuul

一、Ratelimit相关配置介绍

1、限流策略
限流粒度/类型说明
Authenticated User使用经过身份验证的用户名或“匿名”
Request Origin使用用户原始请求
URL使用下游服务的请求路径
ROLE使用经过身份验证的用户角色
Request method使用HTTP请求方法
Global configuration per service这个不验证请求Origin,Authenticated User或URI,要使用这个,请不要设置type
2、可用的实现
存储类型说明
consul基于consul
redis基于redis,使用时必须引入redis相关依赖
JPA基于SpringDataJPA,需要用到数据库
MEMORY基于本地内存,默认
BUKET4J使用一个Java编写的基于令牌桶算法的限流库

Bucket4j实现需要相关的bean @Qualifier(“RateLimit”):

  • JCache - javax.cache.Cache
  • Hazelcast - com.hazelcast.core.IMap
  • Ignite - org.apache.ignite.IgniteCache
  • Infinispan - org.infinispan.functional.ReadWriteMap
3、常见的配置属性
属性名默认值
enabledtrue/falsefalse
behind-proxytrue/falsefalse
add-response-headertrue/falsefalse
key-prefixstring${spring.application.name:rate-limit-application}
repositoryCONSUL, REDIS, JPA, BUCKET4J_JCACHE, BUCKET4J_HAZELCAST, BUCKET4J_INFINISPAN, BUCKET4J_IGNITE-
default-policy-listlist-of-policy-
policy-listMap of Lists of Policy-
postFilterOrderintFilterConstants.SEND_RESPONSE_FILTER_ORDER - 10
preFilterOrderintFilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER

policy的相关属性

属性名默认值
limitnumber of calls-
quotatime of calls-
refresh-intervalseconds60
type[ORIGIN, USER, URL, ROLE][]
4、发生错误如何处理
  @Bean
  public RateLimiterErrorHandler rateLimitErrorHandler() {
    return new DefaultRateLimiterErrorHandler() {
        @Override
        public void handleSaveError(String key, Exception e) {
            // custom code
        }

        @Override
        public void handleFetchError(String key, Exception e) {
            // custom code
        }

        @Override
        public void handleError(String msg, Exception e) {
            // custom code
        }
    }
  }

二、搭建Zuul结合Ratelimit服务

1、导入依赖
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-zuul</artifactId>
</dependency>
<dependency>
    <groupId>com.marcosbarbero.cloud</groupId>
    <artifactId>spring-cloud-zuul-ratelimit</artifactId>
    <version>2.2.3.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
2、启动类标注解
@SpringBootApplication
@EnableEurekaClient
@EnableZuulProxy
public class ZuulRatelimitApplication {
    public static void main(String[] args) {
        SpringApplication.run(ZuulRatelimitApplication.class, args);
    }
}
3、配置文件
server:
  port: 8080
spring:
  application:
    name: zuul-ratelimit
  redis:
    host: localhost
    password: 
zuul:
  # 配置路由
  routes:
    demo:
      path: /demo/**
      serviceId: demo
  # 配置限流
  ratelimit:
    enabled: true
    # 对应存储类型(用来统计存储统计信息)
    repository: redis
    # 配置路由的策略
    policy-list:
      demo:
        # 每秒允许多少个请求
        - limit: 2
          # 刷新时间(单位秒)
          refresh-interval: 1
          # 根据什么统计
          type:
            - url
4、启动后进行访问

由于我们配置的是一秒只允许两个请求,当我们超过时,会抛出过多请求异常
1

到此本文就结束啦,更多相关知识可以前往:spring-cloud-zuul-ratelimit,本demo地址:SpringCloud-Demo

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐