spring cloud 2.x版本 Gateway熔斷、限流教程

前言

本文采用Spring cloud本文爲2.1.8RELEASE,version=Greenwich.SR3

本文基於前兩篇文章eureka-server、eureka-client、eureka-ribbon、eureka-feign和spring-gataway的實現。
參考java

概術

在高併發應用中,緩存、限流、降級,是咱們保護系統應用的三大利器。在開發一些api接口的時候,一般也會在網關層作限流控制,一方面是爲了防止大量的請求是服務器過載,致使服務器不可用,另外一方面也是防止其餘人的惡習網絡攻擊。react

常見的限流方式,如Hystrix的使用線程池隔離,超過線程池的負載走熔斷的邏輯;也有經過滑動的時間窗口來控制流量。git

經常使用的限流算法有,計數器算法、漏桶算法、令牌桶算法,這裏就不對相關算法進行描述。github

熔斷

Spring Cloud Gateway的熔斷能夠基於Hystrix實現。能夠參考spring cloud 2.x版本 Hystrix Dashboard斷路器教程web

1.1 增長pom相關依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>

1.2 修改application.yml

server:
  port: 8100
spring:
  redis:
    host: localhost
    port: 6379
  application:
    name: spring-gateway
  cloud:
      gateway:
        discovery:
          locator:
            enabled: true # 開啓經過服務中心的自動根據 serviceId 建立路由的功能
        default-filters:
          - My=true
        routes:
          - id: ribbon-route
            uri: lb://EUREKA-RIBBON
            order: 0
            predicates:
              - Path=/ribbon/**
            filters:
              - name: Hystrix
                args:
                  name: fallback
                  fallbackUri: forward:/fallback
              - StripPrefix=1 #去掉前綴,具體實現參考StripPrefixGatewayFilterFactory
              - AddResponseHeader=X-Response-Default-Foo, Default-Bar
          - id: feign-route
            uri: lb://EUREKA-FEIGN
            order: 0
            predicates:
              - Path=/feign/**
            filters:
              - StripPrefix=1
              - AddResponseHeader=X-Response-Default-Foo, Default-Bar

eureka:
  instance:
    hostname: eureka1.server.com
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 10
  client:
    service-url:
      defaultZone: http://eureka1.server.com:8701/eureka/,http://eureka2.server.com:8702/eureka/,http://eureka3.server.com:8703/eureka/

只設置ribbon的路由熔斷,feign設置和ribbon相同。redis

  • Hystrix支持兩個參數:算法

    • name:即HystrixCommand的名字
    • fallbackUri:fallback對應的uri,這裏的uri僅支持forward:schemed

1.3 建立FallBackController

package spring.cloud.demo.spring.gateway.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class FallBackController {

    @GetMapping("/fallback")
    public String fallback() {
        return "Error:fallback";
    }
    
}

1.4 啓動相關服務

啓動eureka-server、eureka-client、eureka-ribbon、spring-gateway相關服務,訪問http://localhost:8100/ribbon/sayHello地址,頁面顯示結果以下:

而後咱們將eureka-ribbon服務停掉,刷新頁面,返回結果以下:
spring

至此:熔斷的簡單配置實現就完成了,如需自定義熔斷策略能夠參考HystrixGatewayFilter的內容。api

限流

Spring Cloud Gateway官方提供了RequestRateLimiterGatewayFilterFactory類,使用redis和lua腳原本實現令牌桶的方式。咱們也能夠基於Google Guava中的RateLimiter、Bucket4j、RateLimitJ來實現。本文將採用官方提供的方式來實現。緩存

1.1 增長pom相關依賴

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis-reactive</artifactId>
</dependency>

1.2 修改application.yml配置

server:
  port: 8100
spring:
  redis:
    host: localhost
    port: 6379
  application:
    name: spring-gateway
  cloud:
      gateway:
        discovery:
          locator:
            enabled: true # 開啓經過服務中心的自動根據 serviceId 建立路由的功能
        default-filters:
          - My=true
        routes:
          - id: ribbon-route
            uri: lb://EUREKA-RIBBON
            order: 0
            predicates:
              - Path=/ribbon/**
            filters:
              - name: RequestRateLimiter
                args:
                  key-resolver: '#{@ipKeyResolver}'
                  redis-rate-limiter.replenishRate: 200
                  redis-rate-limiter.burstCapacity: 400
              - name: Hystrix
                args:
                  name: fallback
                  fallbackUri: forward:/fallback
              - StripPrefix=1 #去掉前綴,具體實現參考StripPrefixGatewayFilterFactory
              - AddResponseHeader=X-Response-Default-Foo, Default-Bar
          - id: feign-route
            uri: lb://EUREKA-FEIGN
            order: 0
            predicates:
              - Path=/feign/**
            filters:
              - StripPrefix=1
              - AddResponseHeader=X-Response-Default-Foo, Default-Bar

eureka:
  instance:
    hostname: eureka1.server.com
    lease-renewal-interval-in-seconds: 5
    lease-expiration-duration-in-seconds: 10
  client:
    service-url:
      defaultZone: http://eureka1.server.com:8701/eureka/,http://eureka2.server.com:8702/eureka/,http://eureka3.server.com:8703/eureka/

說明:

  • 1 增長redis相關配置
  • 2.1 -name: RequestRateLimiter, filter的名稱,必須是RequestRateLimiter
  • 2.2 redis-rate-limiter.replenishRate: 容許用戶每秒處理的請求個數
  • 2.3 redis-rate-limiter.burstCapacity: 令牌桶的容量,容許在一秒內完成的最大請求數
  • 2.4 key-resolver: 使用的Bean名稱,規則爲按名稱引用Bean

1.3 增長限流Bean

package spring.cloud.demo.spring.gateway.config;

import org.springframework.cloud.gateway.filter.ratelimit.KeyResolver;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import reactor.core.publisher.Mono;

@Configuration
public class BeanConfig {

    @Bean
    public KeyResolver ipKeyResolver() {
        return exchange -> Mono.just(exchange.getRequest().getRemoteAddress().getHostName());
    }
}

這裏設置的是ip的限流。

1.4 啓動相關服務

首先啓動redis服務,而後順序啓動eureka-server、eureka-client、eureka-ribbon、spring-gateway相關服務,訪問http://localhost:8100/ribbon/sayHello。爲了演示方即可以將redis-rate-limiter.replenishRate和redis-rate-limiter.burstCapacity參數設置成1和3,而後瘋狂刷新頁面能夠看到有請求失敗的狀況(最好使用壓測工具來演示)。同時咱們還要打開redis的監控(monitor命令),能夠看到redis的監控,以下:

說明:redis中會有2個key,request_rate_limiter.{xxx}.timestamp和request_rate_limiter.{xxx}.tokens

總結

本文簡單的實現了Gateway的熔斷和限流。整體來講Spring Cloud Gateway提供的路由網關、過濾器、熔斷、限流仍是都比較簡單,也很是靈活,能夠根據本身的需求來自定義。

代碼地址

gitHub地址


《Srping Cloud 2.X小白教程》目錄
相關文章
相關標籤/搜索