zoukankan      html  css  js  c++  java
  • spring cloud 2.x版本 Gateway熔断、限流教程

    前言

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

    本文基于前两篇文章eureka-server、eureka-client、eureka-ribbon、eureka-feign和spring-gataway的实现。
    参考

    概术

    在高并发应用中,缓存、限流、降级,是我们保护系统应用的三大利器。在开发一些api接口的时候,通常也会在网关层做限流控制,一方面是为了防止大量的请求是服务器过载,导致服务器不可用,另一方面也是防止其他人的恶习网络攻击。

    常见的限流方式,如Hystrix的使用线程池隔离,超过线程池的负载走熔断的逻辑;也有通过滑动的时间窗口来控制流量。

    常用的限流算法有,计数器算法、漏桶算法、令牌桶算法,这里就不对相关算法进行描述。

    熔断

    Spring Cloud Gateway的熔断可以基于Hystrix实现。可以参考spring cloud 2.x版本 Hystrix Dashboard断路器教程

    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相同。

    • 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服务停掉,刷新页面,返回结果如下:

    至此:熔断的简单配置实现就完成了,如需自定义熔断策略可以参考HystrixGatewayFilter的内容。

    限流

    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小白教程》目录

    • 写作不易,转载请注明出处,喜欢的小伙伴可以关注公众号查看更多喜欢的文章,你的每一次查看就是对我最大的支持,你的点赞就是对我最大的鼓励。
    • 联系方式:4272231@163.com
  • 相关阅读:
    Python零基础入门的基础案例
    今天不抠图,Python实现一键换底片!想换什么换什么(附源码)
    python基础:如何使用 pip 安装第三方库
    Python教程:matplotlib 绘制双Y轴曲线图
    福利来啦,送给大家一个小游戏的源码,不要错过哟
    招聘信息太多,哪家职位才是适合你的?Python采集招聘信息
    我的python菜鸟之路1
    我的SAS菜鸟之路3
    我的SAS菜鸟之路2
    猪鹿蝶1
  • 原文地址:https://www.cnblogs.com/fengfujie/p/11820575.html
Copyright © 2011-2022 走看看