限流是保护高并发系统的三把利器之一,另外两个是缓存和降级。限流在很多场景中用来限制并发和请求量,比如说秒杀抢购,保护自身系统和下游系统不被巨型流量冲垮。

     在微服务开发中,我们一般也需要做网关的限流以及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限流node redis限流ralinit_redis

 

同样,我们也可以用redis来做API的限流,大家可以试着做一下,很简单,我们下期直接上代码