微服务开发中有时需要对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