1.概述

前两章文件主要概述了Gateway的三大组件,现在我们继续学习Gateway的其他作用熔断和限流。Gateway是一个网关项目, 网关可以是整个微服务API请求的入口,负责拦截所有请求,分发到服务上去。可以实现日志拦截、权限控制、解决跨域问题、限流、熔断、负载均衡,隐藏服务端的ip,黑名单与白名单拦截、授权等。

2.重试机制

  重试机制就是gateway检测到异常,然后就开始进行重试

引入依赖

        <dependency>
            <groupId>org.springframework.retry</groupId>
            <artifactId>spring-retry</artifactId>
        </dependency>

过滤器配置重试过滤器

spring:
  cloud:
    gateway:
      routes: #1路由
        - id: producer-one
          uri: lb://producter-one
          predicates: #2通过path断言
            - Path=/*/producterone/**
          filters: #3过滤器,过滤器可以不用配置
            - StripPrefix=1  #截断请求PATH
            - name: Retry   #重试过滤器
              args:
                retries: 3   #重试次数
                series: SERVER_ERROR
                methods: GET,POST

        - id: producer-two
          uri: http://localhost:8080
          predicates:
            - Path=/*/productertwo/
          filters:
            - StripPrefix=1

retries:重试次数
series: SERVER_ERROR,下游服务报5XX系列的错误触发重试机制
methods:重试的HTTP方法

3. 熔断降级Hystrix

     熔断降级:在分布式系统中,网关作为流量的入口,大量请求进入网关,向后端远程系统或服务发起调用,后端服务不可避免的会产生调用失败(超时或者异常),失败时不能让请求堆积在网关上,需要快速失败并返回回去,这就需要在网关上做熔断、降级操作。

引入依赖

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>${spring.cloud.version}</version>
        </dependency>

增加熔断降级接口

@RestController
public class GatewayController {

    @GetMapping("fallback")
    public String hello() {
        return "Hystrix 熔断降级";
    }
}

增加熔断过滤器以及配置熔断时间(熔断时间<Gateway超时时间,不然会先触发gateway超时不会触发熔断)

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes: #1路由
        - id: producer-one
          uri: lb://producter-one
          predicates: #2通过path断言
            - Path=/*/producterone/**
          filters: #3过滤器,过滤器可以不用配置
            - StripPrefix=1  #截断请求PATH,去掉前缀gateway再请求
            #局部过滤器熔断Hystrix
            - name: Hystrix  
              args:
                name: localfallback
                fallbackUri: forward:/gateway/fallback   #熔断转发到其他URL
        - id: producer-two
          uri: http://localhost:8080
          predicates:
            - Path=/*/productertwo/
          filters:
            - StripPrefix=1
      httpclient:   #全局设置gateway超时设置
        response-timeout: 30000   #必须以毫秒为单位指定响应超时时间.
        connect-timeout: 30000    #必须以毫秒为单位指定连接超时时间.

## hystrix ,3秒后自动超时
hystrix:
  command:
    default:  #default全局有效,service id指定应用有效
      execution:
        timeout:
          enabled: true     #如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为熔断根据
        isolation:
          thread:
            timeoutInMilliseconds: 3000

4.限流

    限流:网关上有大量请求,对指定服务进行限流,可以很大程度上提高服务的可用性与稳定性,限流的目的是通过对并发访问/请求进行限速,或对一个时间窗口内的请求进行限速来保护系统。一旦达到限制速率则可以拒绝服务、排队或等待、降级,同一时间限制访问的人数

限流框架:基于 redis和阿里开源的限流神器 Sentinel
限流的算法:
        1.漏桶算法:把请求放到一个容器中,控制处理的速度
        2. 令牌算法:给每一个请求分配一个令牌,没有令牌的访问不了,1/QPS (同一时间接口的访问数一般一个tomcat是200~250)。

这里就用redis实现限流。

引入redis连接依赖

     #未设置版本号,使用spring-boot-starter-parent的  
      <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
        </dependency>

增加KeyResolver的实例

@Configuration
@Slf4j
public class CustomeKeyResolverConfig {

    @Primary
    @Bean(value = "hostAddKeyResolver")
    public KeyResolver hostAddKeyResolver() {
        // 根据IP地址限流
        KeyResolver keyResolver = (exchange) -> {
            String hostAddress = exchange.getRequest().getRemoteAddress().getAddress().getHostAddress();
            log.info("hostAddress={}", hostAddress);
            return Mono.just(hostAddress);
        };
        return keyResolver;
    }

    @Bean("uriPathKeyResolver")
    public KeyResolver uriPathKeyResolver() {
        // 根据请求地址限流
        KeyResolver keyResolver = (exchange) -> {
            String uriPath = exchange.getRequest().getURI().getPath();
            log.info("uriPath={}", uriPath);
            return Mono.just(uriPath);
        };
        return keyResolver;
    }
}

配置访问限制过滤器RequestRateLimiter

spring:
  application:
    name: gateway-server
  cloud:
    gateway:
      routes: #1路由
        - id: producer-one
          uri: lb://producter-one
          predicates: #2通过path断言
            - Path=/*/producterone/**
          filters: #3过滤器,过滤器可以不用配置
            - StripPrefix=1  #截断请求PATH,去掉前缀gateway再请求
            #局部过滤器熔断Hystrix
            - name: Hystrix
              args:
                name: localfallback
                fallbackUri: forward:/gateway/fallback   #熔断转发到其他URL
            #局部过滤器熔断RequestRateLimiter
            - name: RequestRateLimiter
              args:
                key-resolver: '#{@hostAddKeyResolver}'    # 使用SpEL名称引用Bean
                redis-rate-limiter.replenishRate: 1 #每秒最大访问次数
                redis-rate-limiter.burstCapacity: 3 #令牌桶最大容量
        - id: producer-two
          uri: http://localhost:8080
          predicates:
            - Path=/*/productertwo/
          filters:
            - StripPrefix=1
      httpclient: #全局设置gateway超时设置
        response-timeout: 30000   #必须以毫秒为单位指定响应超时时间.
        connect-timeout: 30000    #必须以毫秒为单位指定连接超时时间.

## hystrix ,3秒后自动超时
hystrix:
  command:
    default: #default全局有效,service id指定应用有效
      execution:
        timeout:
          enabled: true     #如果enabled设置为false,则请求超时交给ribbon控制,为true,则超时作为熔断根据
        isolation:
          thread:
            timeoutInMilliseconds: 3000
  # redis连接配置
  redis:
    host: 127.0.0.1
    port: 36379
    password: redis
    database: 0

filter名称必须是RequestRateLimiter
redis-rate-limiter.replenishRate:允许用户每秒处理多少个请求
redis-rate-limiter.burstCapacity:令牌桶的容量,允许在一秒钟内完成的最大请求数
key-resolver:使用SpEL按名称引用bean 

启动服务频繁访问

 5.其他方式限流

方式1:阿里开源限流神器:Sentinel

方式2:自定义过滤器实现令牌桶算法限流

参考:

SpringCloud之Gateway网关熔断、限流_yzm4399的博客-CSDN博客_gateway 熔断

Spring cloud 之限流 - 知乎

Logo

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

更多推荐