限流是保护高并发系统的三把利器之一,另外两个是缓存和降级。限流在很多场景中用来限制并发和请求量,比如说秒杀抢购,保护自身系统和下游系统不被巨型流量冲垮。
在微服务开发中,我们一般也需要做网关的限流以及API的限流,来保护我们的系统。限流的目的是通过对并发访问/请求进行限速或者一个时间窗口内的的请求进行限速来保护系统,一旦达到限制速率则可以拒绝服务或进行流量整形。例如,Zuul+RateLimter就可以实现限流功能
本文主要侧重讲解配置和使用,如果对Ratelimit的限流原理有不了解的,还请大家自行度娘,主要就两个算法,一个漏桶算法,一个令牌桶算法
一、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编写的基于令牌桶算法的限流库 |
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] | |
二、搭建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.4.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!-- security boot 2.1.5 使用redis必须引入security-jar 包-->
<dependency >
<groupId >org.springframework.boot</groupId >
<artifactId >spring-boot-starter-security</artifactId >
</dependency >
2、启动类标注解
/**
* RefreshScope:开启自动刷新,配置文件更改后不需要重启
* EnableZuulProxy:开启网关,自带熔断器和负载均衡
* EnableRedisHttpSession 开启redis管理session注解
* @author lenovo
*/
@SpringBootApplication
@EnableDiscoveryClient
@EnableZuulProxy
//@RefreshScope
@Slf4j
@ComponentScan("com.XXX")
public class ZuulApplication implements CommandLineRunner {
public static void main(String[] args) {
SpringApplication.run(ZuulApplication.class, args);
}
@Override
public void run(String... args) throws Exception {
log.info("************************Gateway zuul Started****************************************");
}
}
3、配置文件
server:
port: 8080
spring:
application:
name: zuul-ratelimit
redis:
host: localhost
password: 123456
zuul:
# 配置路由
routes:
demo:
path: /demo/**
serviceId: demo
# 配置限流
ratelimit:
enabled: true
repository: redis
behind-proxy: true
add-response-headers: true
policy-list:
inter-api:
- limit: 50
refresh-interval: 1
type:
- url
# - origin
# - user
4、访问,当前配置的是1秒钟,最多接受50个请求,当我们超过时,会抛出429异常
同样,我们也可以用redis来做API的限流,大家可以试着做一下,很简单,我们下期直接上代码