微服务开发中有时需要对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、常见的配置属性
属性名 |
值 |
默认值 |
enabled |
true/false |
false |
behind-proxy |
true/false |
false |
add-response-header |
true/false |
false |
key-prefix |
string |
${spring.application.name:rate-limit-application} |
repository |
CONSUL, REDIS, JPA, BUCKET4J_JCACHE, BUCKET4J_HAZELCAST, BUCKET4J_INFINISPAN, BUCKET4J_IGNITE |
- |
default-policy-list |
list-of-policy |
- |
policy-list |
Map of Lists of Policy |
- |
postFilterOrder |
int |
FilterConstants.SEND_RESPONSE_FILTER_ORDER - 10 |
preFilterOrder |
int |
FilterConstants.FORM_BODY_WRAPPER_FILTER_ORDER |
policy的相关属性
属性名 |
值 |
默认值 |
limit |
number of calls |
- |
quota |
time of calls |
- |
refresh-interval |
seconds |
60 |
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、启动后进行访问
由于我们配置的是一秒只允许两个请求,当我们超过时,会抛出过多请求异常

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